Skip to contentSkip to conversation

mmc: meson: add MMC support for Meson GX (S905)

PATCH New Heiner Kallweit 8 participants 59 messages Apr 12, 2017 – Apr 29, 2017

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

v7 cover mmc: meson: add MMC support for Meson GX (S905)

This patch set implements eMMC on Amlogic Meson GX (S905). It's based on Carlo Caione's work submitted here:
http://lists.denx.de/pipermail/u-boot/2016-May/254391.html

Changes to the original version:
- BLK support added
- fully DT-based now
- minor general refactoring

The driver was successfully tested on a Odroid C2.

Note: On Odroid C2 eMMC is MMC device 1. So you have to switch from MMC device 0 to 1 first when testing from uboot prompt.

Latest change in v7:
- rebase due to other recent mmc changes

Heiner Kallweit (3):
arm: dts: update Meson GXBB / Odroid-C2 DT with recent Linux version
mmc: meson: add MMC driver for Meson GX (S905)
odroid-c2: enable new Meson GX MMC driver in board defconfig

 arch/arm/dts/meson-gx.dtsi                | 447 +++++++++++++++++++
 arch/arm/dts/meson-gxbb-odroidc2.dts      | 147 +++++-
 arch/arm/dts/meson-gxbb.dtsi              | 718 ++++++++++++++++++------------
 arch/arm/include/asm/arch-meson/sd_emmc.h |  89 ++++
 configs/odroid-c2_defconfig               |   5 +-
 drivers/mmc/Kconfig                       |   6 +
 drivers/mmc/Makefile                      |   1 +
 drivers/mmc/meson_gx_mmc.c                | 291 ++++++++++++
 include/dt-bindings/clock/gxbb-aoclkc.h   |  66 +++
 include/dt-bindings/clock/gxbb-clkc.h     |  34 ++
 include/dt-bindings/reset/gxbb-aoclkc.h   |  66 +++
 11 files changed, 1594 insertions(+), 276 deletions(-)
 create mode 100644 arch/arm/dts/meson-gx.dtsi
 create mode 100644 arch/arm/include/asm/arch-meson/sd_emmc.h
 create mode 100644 drivers/mmc/meson_gx_mmc.c
 create mode 100644 include/dt-bindings/clock/gxbb-aoclkc.h
 create mode 100644 include/dt-bindings/clock/gxbb-clkc.h
 create mode 100644 include/dt-bindings/reset/gxbb-aoclkc.h
Signature · 1 line
2.12.2
#1 lore raw

PATCH v7 1/3 arm: dts: update Meson GXBB / Odroid-C2 DT with recent Linux version

As a prerequisite for adding a Meson GX MMC driver update the Meson GXBB / Odroid-C2 device tree in Uboot with the latest version from Linux.

---
v4:
- Added SoB of original authors
v5:
- no changes
v6:
- changed prefix in subject
v7:
- rebased

---
 arch/arm/dts/meson-gx.dtsi              | 447 ++++++++++++++++++++
 arch/arm/dts/meson-gxbb-odroidc2.dts    | 147 ++++++-
 arch/arm/dts/meson-gxbb.dtsi            | 718 ++++++++++++++++++++------------
 include/dt-bindings/clock/gxbb-aoclkc.h |  66 +++
 include/dt-bindings/clock/gxbb-clkc.h   |  34 ++
 include/dt-bindings/reset/gxbb-aoclkc.h |  66 +++
 6 files changed, 1203 insertions(+), 275 deletions(-)
 create mode 100644 arch/arm/dts/meson-gx.dtsi
 create mode 100644 include/dt-bindings/clock/gxbb-aoclkc.h
 create mode 100644 include/dt-bindings/clock/gxbb-clkc.h
 create mode 100644 include/dt-bindings/reset/gxbb-aoclkc.h
arch/arm/dts/meson-gx.dtsi new file +447 -0
new file mode 100644
index 0000000..c129100
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <[email protected]>
+ *
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <[email protected]>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library 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 library 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* 16 MiB reserved for Hardware ROM Firmware */
+		hwrom_reserved: hwrom at 0 {
+			reg = <0x0 0x0 0x0 0x1000000>;
+			no-map;
+		};
+
+		/* 2 MiB reserved for ARM Trusted Firmware (BL31) */
+		secmon_reserved: secmon at 10000000 {
+			reg = <0x0 0x10000000 0x0 0x200000>;
+			no-map;
+		};
+	};
+
+	cpus {
+		#address-cells = <0x2>;
+		#size-cells = <0x0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+			clocks = <&scpi_dvfs 0>;
+		};
+
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+			clocks = <&scpi_dvfs 0>;
+		};
+
+		cpu2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+			clocks = <&scpi_dvfs 0>;
+		};
+
+		cpu3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+			clocks = <&scpi_dvfs 0>;
+		};
+
+		l2: l2-cache0 {
+			compatible = "cache";
+		};
+	};
+
+	arm-pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	xtal: xtal-clk {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xtal";
+		#clock-cells = <0>;
+	};
+
+	firmware {
+		sm: secure-monitor {
+			compatible = "amlogic,meson-gx-sm", "amlogic,meson-gxbb-sm";
+		};
+	};
+
+	efuse: efuse {
+		compatible = "amlogic,meson-gx-efuse", "amlogic,meson-gxbb-efuse";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		sn: sn at 14 {
+			reg = <0x14 0x10>;
+		};
+
+		eth_mac: eth_mac at 34 {
+			reg = <0x34 0x10>;
+		};
+
+		bid: bid at 46 {
+			reg = <0x46 0x30>;
+		};
+	};
+
+	scpi {
+		compatible = "amlogic,meson-gxbb-scpi", "arm,scpi-pre-1.0";
+		mboxes = <&mailbox 1 &mailbox 2>;
+		shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
+
+		scpi_clocks: clocks {
+			compatible = "arm,scpi-clocks";
+
+			scpi_dvfs: scpi_clocks at 0 {
+				compatible = "arm,scpi-dvfs-clocks";
+				#clock-cells = <1>;
+				clock-indices = <0>;
+				clock-output-names = "vcpu";
+			};
+		};
+
+		scpi_sensors: sensors {
+			compatible = "arm,scpi-sensors";
+			#thermal-sensor-cells = <1>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cbus: cbus at c1100000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc1100000 0x0 0x100000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
+
+			reset: reset-controller at 4404 {
+				compatible = "amlogic,meson-gx-reset", "amlogic,meson-gxbb-reset";
+				reg = <0x0 0x04404 0x0 0x20>;
+				#reset-cells = <1>;
+			};
+
+			uart_A: serial at 84c0 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x84c0 0x0 0x14>;
+				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			uart_B: serial at 84dc {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x84dc 0x0 0x14>;
+				interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			i2c_A: i2c at 8500 {
+				compatible = "amlogic,meson-gxbb-i2c";
+				reg = <0x0 0x08500 0x0 0x20>;
+				interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			pwm_ab: pwm at 8550 {
+				compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x08550 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			pwm_cd: pwm at 8650 {
+				compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x08650 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			pwm_ef: pwm at 86c0 {
+				compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x086c0 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			uart_C: serial at 8700 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x8700 0x0 0x14>;
+				interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			i2c_B: i2c at 87c0 {
+				compatible = "amlogic,meson-gxbb-i2c";
+				reg = <0x0 0x087c0 0x0 0x20>;
+				interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			i2c_C: i2c at 87e0 {
+				compatible = "amlogic,meson-gxbb-i2c";
+				reg = <0x0 0x087e0 0x0 0x20>;
+				interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			watchdog at 98d0 {
+				compatible = "amlogic,meson-gx-wdt", "amlogic,meson-gxbb-wdt";
+				reg = <0x0 0x098d0 0x0 0x10>;
+				clocks = <&xtal>;
+			};
+		};
+
+		gic: interrupt-controller at c4301000 {
+			compatible = "arm,gic-400";
+			reg = <0x0 0xc4301000 0 0x1000>,
+			      <0x0 0xc4302000 0 0x2000>,
+			      <0x0 0xc4304000 0 0x2000>,
+			      <0x0 0xc4306000 0 0x2000>;
+			interrupt-controller;
+			interrupts = <GIC_PPI 9
+				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+		};
+
+		sram: sram at c8000000 {
+			compatible = "amlogic,meson-gxbb-sram", "mmio-sram";
+			reg = <0x0 0xc8000000 0x0 0x14000>;
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x0 0xc8000000 0x14000>;
+
+			cpu_scp_lpri: scp-shmem at 0 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
+				reg = <0x13000 0x400>;
+			};
+
+			cpu_scp_hpri: scp-shmem at 200 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
+				reg = <0x13400 0x400>;
+			};
+		};
+
+		aobus: aobus at c8100000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc8100000 0x0 0x100000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
+
+			uart_AO: serial at 4c0 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x004c0 0x0 0x14>;
+				interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			uart_AO_B: serial at 4e0 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x004e0 0x0 0x14>;
+				interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			ir: ir at 580 {
+				compatible = "amlogic,meson-gxbb-ir";
+				reg = <0x0 0x00580 0x0 0x40>;
+				interrupts = <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+		};
+
+		periphs: periphs at c8834000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc8834000 0x0 0x2000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>;
+
+			rng {
+				compatible = "amlogic,meson-rng";
+				reg = <0x0 0x0 0x0 0x4>;
+			};
+		};
+
+
+		hiubus: hiubus at c883c000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc883c000 0x0 0x2000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>;
+
+			mailbox: mailbox at 404 {
+				compatible = "amlogic,meson-gx-mhu", "amlogic,meson-gxbb-mhu";
+				reg = <0 0x404 0 0x4c>;
+				interrupts = <0 208 IRQ_TYPE_EDGE_RISING>,
+					     <0 209 IRQ_TYPE_EDGE_RISING>,
+					     <0 210 IRQ_TYPE_EDGE_RISING>;
+				#mbox-cells = <1>;
+			};
+		};
+
+		ethmac: ethernet at c9410000 {
+			compatible = "amlogic,meson-gx-dwmac", "amlogic,meson-gxbb-dwmac", "snps,dwmac";
+			reg = <0x0 0xc9410000 0x0 0x10000
+			       0x0 0xc8834540 0x0 0x4>;
+			interrupts = <0 8 1>;
+			interrupt-names = "macirq";
+			phy-mode = "rgmii";
+			status = "disabled";
+		};
+
+		apb: apb at d0000000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xd0000000 0x0 0x200000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
+
+			sd_emmc_a: mmc at 70000 {
+				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x70000 0x0 0x2000>;
+				interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+
+			sd_emmc_b: mmc at 72000 {
+				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x72000 0x0 0x2000>;
+				interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+
+			sd_emmc_c: mmc at 74000 {
+				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x74000 0x0 0x2000>;
+				interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+		};
+
+		vpu: vpu at d0100000 {
+			compatible = "amlogic,meson-gx-vpu";
+			reg = <0x0 0xd0100000 0x0 0x100000>,
+			      <0x0 0xc883c000 0x0 0x1000>,
+			      <0x0 0xc8838000 0x0 0x1000>;
+			reg-names = "vpu", "hhi", "dmc";
+			interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* CVBS VDAC output port */
+			cvbs_vdac_port: port at 0 {
+				reg = <0>;
+			};
+		};
+	};
+};
arch/arm/dts/meson-gxbb-odroidc2.dts +146 -1

164 lines not on this page · raw message

arch/arm/dts/meson-gxbb.dtsi +444 -274

751 lines not on this page · raw message

include/dt-bindings/clock/gxbb-aoclkc.h new file +66 -0

66 lines not on this page · raw message

include/dt-bindings/clock/gxbb-clkc.h new file +34 -0
new file mode 100644
index 0000000..692846c
@@ -0,0 +1,34 @@
+/*
+ * GXBB clock tree IDs
+ */
+
+#ifndef __GXBB_CLKC_H
+#define __GXBB_CLKC_H
+
+#define CLKID_CPUCLK		1
+#define CLKID_HDMI_PLL		2
+#define CLKID_FCLK_DIV2		4
+#define CLKID_FCLK_DIV3		5
+#define CLKID_FCLK_DIV4		6
+#define CLKID_CLK81		12
+#define CLKID_MPLL2		15
+#define CLKID_SPI		34
+#define CLKID_I2C		22
+#define CLKID_SAR_ADC		23
+#define CLKID_ETH		36
+#define CLKID_USB0		50
+#define CLKID_USB1		51
+#define CLKID_USB		55
+#define CLKID_HDMI_PCLK		63
+#define CLKID_USB1_DDR_BRIDGE	64
+#define CLKID_USB0_DDR_BRIDGE	65
+#define CLKID_SANA		69
+#define CLKID_GCLK_VENCI_INT0	77
+#define CLKID_AO_I2C		93
+#define CLKID_SD_EMMC_A		94
+#define CLKID_SD_EMMC_B		95
+#define CLKID_SD_EMMC_C		96
+#define CLKID_SAR_ADC_CLK	97
+#define CLKID_SAR_ADC_SEL	98
+
+#endif /* __GXBB_CLKC_H */
include/dt-bindings/reset/gxbb-aoclkc.h new file +66 -0

66 lines not on this page · raw message

Signature · 1 line
2.12.2
#2 lore raw

PATCH v7 1/3 arm: dts: update Meson GXBB / Odroid-C2 DT with recent Linux version

Quoted 8 lines · Heiner Kallweit

As a prerequisite for adding a Meson GX MMC driver update the Meson GXBB / Odroid-C2 device tree in Uboot with the latest version from Linux.

Applied to u-boot-mmc. Thanks!

Best Regards,
Jaehoon Chung

Quoted 1,587 lines

---
v4:
- Added SoB of original authors
v5:
- no changes
v6:
- changed prefix in subject
v7:
- rebased

---
 arch/arm/dts/meson-gx.dtsi              | 447 ++++++++++++++++++++
 arch/arm/dts/meson-gxbb-odroidc2.dts    | 147 ++++++-
 arch/arm/dts/meson-gxbb.dtsi            | 718 ++++++++++++++++++++------------
 include/dt-bindings/clock/gxbb-aoclkc.h |  66 +++
 include/dt-bindings/clock/gxbb-clkc.h   |  34 ++
 include/dt-bindings/reset/gxbb-aoclkc.h |  66 +++
 6 files changed, 1203 insertions(+), 275 deletions(-)
 create mode 100644 arch/arm/dts/meson-gx.dtsi
 create mode 100644 include/dt-bindings/clock/gxbb-aoclkc.h
 create mode 100644 include/dt-bindings/clock/gxbb-clkc.h
 create mode 100644 include/dt-bindings/reset/gxbb-aoclkc.h
arch/arm/dts/meson-gx.dtsi new file +447 -0
new file mode 100644
index 0000000..c129100
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <[email protected]>
+ *
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <[email protected]>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library 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 library 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* 16 MiB reserved for Hardware ROM Firmware */
+		hwrom_reserved: hwrom at 0 {
+			reg = <0x0 0x0 0x0 0x1000000>;
+			no-map;
+		};
+
+		/* 2 MiB reserved for ARM Trusted Firmware (BL31) */
+		secmon_reserved: secmon at 10000000 {
+			reg = <0x0 0x10000000 0x0 0x200000>;
+			no-map;
+		};
+	};
+
+	cpus {
+		#address-cells = <0x2>;
+		#size-cells = <0x0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+			clocks = <&scpi_dvfs 0>;
+		};
+
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+			clocks = <&scpi_dvfs 0>;
+		};
+
+		cpu2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+			clocks = <&scpi_dvfs 0>;
+		};
+
+		cpu3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+			clocks = <&scpi_dvfs 0>;
+		};
+
+		l2: l2-cache0 {
+			compatible = "cache";
+		};
+	};
+
+	arm-pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	xtal: xtal-clk {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xtal";
+		#clock-cells = <0>;
+	};
+
+	firmware {
+		sm: secure-monitor {
+			compatible = "amlogic,meson-gx-sm", "amlogic,meson-gxbb-sm";
+		};
+	};
+
+	efuse: efuse {
+		compatible = "amlogic,meson-gx-efuse", "amlogic,meson-gxbb-efuse";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		sn: sn at 14 {
+			reg = <0x14 0x10>;
+		};
+
+		eth_mac: eth_mac at 34 {
+			reg = <0x34 0x10>;
+		};
+
+		bid: bid at 46 {
+			reg = <0x46 0x30>;
+		};
+	};
+
+	scpi {
+		compatible = "amlogic,meson-gxbb-scpi", "arm,scpi-pre-1.0";
+		mboxes = <&mailbox 1 &mailbox 2>;
+		shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
+
+		scpi_clocks: clocks {
+			compatible = "arm,scpi-clocks";
+
+			scpi_dvfs: scpi_clocks at 0 {
+				compatible = "arm,scpi-dvfs-clocks";
+				#clock-cells = <1>;
+				clock-indices = <0>;
+				clock-output-names = "vcpu";
+			};
+		};
+
+		scpi_sensors: sensors {
+			compatible = "arm,scpi-sensors";
+			#thermal-sensor-cells = <1>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cbus: cbus at c1100000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc1100000 0x0 0x100000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
+
+			reset: reset-controller at 4404 {
+				compatible = "amlogic,meson-gx-reset", "amlogic,meson-gxbb-reset";
+				reg = <0x0 0x04404 0x0 0x20>;
+				#reset-cells = <1>;
+			};
+
+			uart_A: serial at 84c0 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x84c0 0x0 0x14>;
+				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			uart_B: serial at 84dc {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x84dc 0x0 0x14>;
+				interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			i2c_A: i2c at 8500 {
+				compatible = "amlogic,meson-gxbb-i2c";
+				reg = <0x0 0x08500 0x0 0x20>;
+				interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			pwm_ab: pwm at 8550 {
+				compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x08550 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			pwm_cd: pwm at 8650 {
+				compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x08650 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			pwm_ef: pwm at 86c0 {
+				compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x086c0 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			uart_C: serial at 8700 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x8700 0x0 0x14>;
+				interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			i2c_B: i2c at 87c0 {
+				compatible = "amlogic,meson-gxbb-i2c";
+				reg = <0x0 0x087c0 0x0 0x20>;
+				interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			i2c_C: i2c at 87e0 {
+				compatible = "amlogic,meson-gxbb-i2c";
+				reg = <0x0 0x087e0 0x0 0x20>;
+				interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			watchdog at 98d0 {
+				compatible = "amlogic,meson-gx-wdt", "amlogic,meson-gxbb-wdt";
+				reg = <0x0 0x098d0 0x0 0x10>;
+				clocks = <&xtal>;
+			};
+		};
+
+		gic: interrupt-controller at c4301000 {
+			compatible = "arm,gic-400";
+			reg = <0x0 0xc4301000 0 0x1000>,
+			      <0x0 0xc4302000 0 0x2000>,
+			      <0x0 0xc4304000 0 0x2000>,
+			      <0x0 0xc4306000 0 0x2000>;
+			interrupt-controller;
+			interrupts = <GIC_PPI 9
+				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+		};
+
+		sram: sram at c8000000 {
+			compatible = "amlogic,meson-gxbb-sram", "mmio-sram";
+			reg = <0x0 0xc8000000 0x0 0x14000>;
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x0 0xc8000000 0x14000>;
+
+			cpu_scp_lpri: scp-shmem at 0 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
+				reg = <0x13000 0x400>;
+			};
+
+			cpu_scp_hpri: scp-shmem at 200 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
+				reg = <0x13400 0x400>;
+			};
+		};
+
+		aobus: aobus at c8100000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc8100000 0x0 0x100000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
+
+			uart_AO: serial at 4c0 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x004c0 0x0 0x14>;
+				interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			uart_AO_B: serial at 4e0 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x004e0 0x0 0x14>;
+				interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			ir: ir at 580 {
+				compatible = "amlogic,meson-gxbb-ir";
+				reg = <0x0 0x00580 0x0 0x40>;
+				interrupts = <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+		};
+
+		periphs: periphs at c8834000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc8834000 0x0 0x2000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>;
+
+			rng {
+				compatible = "amlogic,meson-rng";
+				reg = <0x0 0x0 0x0 0x4>;
+			};
+		};
+
+
+		hiubus: hiubus at c883c000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc883c000 0x0 0x2000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>;
+
+			mailbox: mailbox at 404 {
+				compatible = "amlogic,meson-gx-mhu", "amlogic,meson-gxbb-mhu";
+				reg = <0 0x404 0 0x4c>;
+				interrupts = <0 208 IRQ_TYPE_EDGE_RISING>,
+					     <0 209 IRQ_TYPE_EDGE_RISING>,
+					     <0 210 IRQ_TYPE_EDGE_RISING>;
+				#mbox-cells = <1>;
+			};
+		};
+
+		ethmac: ethernet at c9410000 {
+			compatible = "amlogic,meson-gx-dwmac", "amlogic,meson-gxbb-dwmac", "snps,dwmac";
+			reg = <0x0 0xc9410000 0x0 0x10000
+			       0x0 0xc8834540 0x0 0x4>;
+			interrupts = <0 8 1>;
+			interrupt-names = "macirq";
+			phy-mode = "rgmii";
+			status = "disabled";
+		};
+
+		apb: apb at d0000000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xd0000000 0x0 0x200000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
+
+			sd_emmc_a: mmc at 70000 {
+				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x70000 0x0 0x2000>;
+				interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+
+			sd_emmc_b: mmc at 72000 {
+				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x72000 0x0 0x2000>;
+				interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+
+			sd_emmc_c: mmc at 74000 {
+				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x74000 0x0 0x2000>;
+				interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+		};
+
+		vpu: vpu at d0100000 {
+			compatible = "amlogic,meson-gx-vpu";
+			reg = <0x0 0xd0100000 0x0 0x100000>,
+			      <0x0 0xc883c000 0x0 0x1000>,
+			      <0x0 0xc8838000 0x0 0x1000>;
+			reg-names = "vpu", "hhi", "dmc";
+			interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* CVBS VDAC output port */
+			cvbs_vdac_port: port at 0 {
+				reg = <0>;
+			};
+		};
+	};
+};
arch/arm/dts/meson-gxbb-odroidc2.dts +146 -1
index 79bee64..c737183 100644
@@ -64,6 +64,18 @@
 		reg = <0x0 0x0 0x0 0x80000000>;
 	};
 
+	usb_otg_pwr: regulator-usb-pwrs {
+		compatible = "regulator-fixed";
+
+		regulator-name = "USB_OTG_PWR";
+
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+
+		gpio = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
 	leds {
 		compatible = "gpio-leds";
 		blue {
@@ -73,6 +85,60 @@
 			default-state = "off";
 		};
 	};
+
+	tflash_vdd: regulator-tflash_vdd {
+		/*
+		 * signal name from schematics: TFLASH_VDD_EN
+		 */
+		compatible = "regulator-fixed";
+
+		regulator-name = "TFLASH_VDD";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio_ao GPIOAO_12 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	tf_io: gpio-regulator-tf_io {
+		compatible = "regulator-gpio";
+
+		regulator-name = "TF_IO";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		/*
+		 * signal name from schematics: TF_3V3N_1V8_EN
+		 */
+		gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
+		gpios-states = <0>;
+
+		states = <3300000 0
+			  1800000 1>;
+	};
+
+	vcc1v8: regulator-vcc1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC1V8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vcc3v3: regulator-vcc3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&scpi_clocks {
+	status = "disabled";
 };
 
 &uart_AO {
@@ -83,6 +149,85 @@
 
 &ethmac {
 	status = "okay";
-	pinctrl-0 = <&eth_pins>;
+	pinctrl-0 = <&eth_rgmii_pins>;
+	pinctrl-names = "default";
+	phy-handle = <&eth_phy0>;
+
+	mdio {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		eth_phy0: ethernet-phy at 0 {
+			reg = <0>;
+			eee-broken-1000t;
+		};
+	};
+};
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&remote_input_ao_pins>;
 	pinctrl-names = "default";
 };
+
+&i2c_A {
+	status = "okay";
+	pinctrl-0 = <&i2c_a_pins>;
+	pinctrl-names = "default";
+};
+
+&usb0_phy {
+	status = "okay";
+	phy-supply = <&usb_otg_pwr>;
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+};
+
+/* SD */
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&tflash_vdd>;
+	vqmmc-supply = <&tf_io>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	cap-mmc-highspeed;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc3v3>;
+	vqmmc-supply = <&vcc1v8>;
+};
arch/arm/dts/meson-gxbb.dtsi +444 -274
index e502c24..39a774a 100644
@@ -40,307 +40,477 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "meson-gx.dtsi"
 #include <dt-bindings/gpio/meson-gxbb-gpio.h>
 #include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
+#include <dt-bindings/clock/gxbb-clkc.h>
+#include <dt-bindings/clock/gxbb-aoclkc.h>
+#include <dt-bindings/reset/gxbb-aoclkc.h>
 
 / {
 	compatible = "amlogic,meson-gxbb";
-	interrupt-parent = <&gic>;
-	#address-cells = <2>;
-	#size-cells = <2>;
 
-	cpus {
-		#address-cells = <0x2>;
-		#size-cells = <0x0>;
-
-		cpu0: cpu at 0 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x0>;
-			enable-method = "psci";
+	soc {
+		usb0_phy: phy at c0000000 {
+			compatible = "amlogic,meson-gxbb-usb2-phy";
+			#phy-cells = <0>;
+			reg = <0x0 0xc0000000 0x0 0x20>;
+			resets = <&reset RESET_USB_OTG>;
+			clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>;
+			clock-names = "usb_general", "usb";
+			status = "disabled";
 		};
 
-		cpu1: cpu at 1 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x1>;
-			enable-method = "psci";
+		usb1_phy: phy at c0000020 {
+			compatible = "amlogic,meson-gxbb-usb2-phy";
+			#phy-cells = <0>;
+			reg = <0x0 0xc0000020 0x0 0x20>;
+			resets = <&reset RESET_USB_OTG>;
+			clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB1>;
+			clock-names = "usb_general", "usb";
+			status = "disabled";
 		};
 
-		cpu2: cpu at 2 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x2>;
-			enable-method = "psci";
+		usb0: usb at c9000000 {
+			compatible = "amlogic,meson-gxbb-usb", "snps,dwc2";
+			reg = <0x0 0xc9000000 0x0 0x40000>;
+			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clkc CLKID_USB0_DDR_BRIDGE>;
+			clock-names = "otg";
+			phys = <&usb0_phy>;
+			phy-names = "usb2-phy";
+			dr_mode = "host";
+			status = "disabled";
 		};
 
-		cpu3: cpu at 3 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x3>;
-			enable-method = "psci";
+		usb1: usb at c9100000 {
+			compatible = "amlogic,meson-gxbb-usb", "snps,dwc2";
+			reg = <0x0 0xc9100000 0x0 0x40000>;
+			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
+			clock-names = "otg";
+			phys = <&usb1_phy>;
+			phy-names = "usb2-phy";
+			dr_mode = "host";
+			status = "disabled";
 		};
 	};
+};
 
-	arm-pmu {
-		compatible = "arm,cortex-a53-pmu";
-		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
-		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+&cbus {
+	spifc: spi at 8c80 {
+		compatible = "amlogic,meson-gxbb-spifc";
+		reg = <0x0 0x08c80 0x0 0x80>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&clkc CLKID_SPI>;
+		status = "disabled";
 	};
+};
+
+&ethmac {
+	clocks = <&clkc CLKID_ETH>,
+		 <&clkc CLKID_FCLK_DIV2>,
+		 <&clkc CLKID_MPLL2>;
+	clock-names = "stmmaceth", "clkin0", "clkin1";
+};
+
+&aobus {
+	pinctrl_aobus: pinctrl at 14 {
+		compatible = "amlogic,meson-gxbb-aobus-pinctrl";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gpio_ao: bank at 14 {
+			reg = <0x0 0x00014 0x0 0x8>,
+			      <0x0 0x0002c 0x0 0x4>,
+			      <0x0 0x00024 0x0 0x8>;
+			reg-names = "mux", "pull", "gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		uart_ao_a_pins: uart_ao_a {
+			mux {
+				groups = "uart_tx_ao_a", "uart_rx_ao_a";
+				function = "uart_ao";
+			};
+		};
+
+		uart_ao_a_cts_rts_pins: uart_ao_a_cts_rts {
+			mux {
+				groups = "uart_cts_ao_a",
+				       "uart_rts_ao_a";
+				function = "uart_ao";
+			};
+		};
+
+		uart_ao_b_pins: uart_ao_b {
+			mux {
+				groups = "uart_tx_ao_b", "uart_rx_ao_b";
+				function = "uart_ao_b";
+			};
+		};
+
+		uart_ao_b_cts_rts_pins: uart_ao_b_cts_rts {
+			mux {
+				groups = "uart_cts_ao_b",
+				       "uart_rts_ao_b";
+				function = "uart_ao_b";
+			};
+		};
 
-	psci {
-		compatible = "arm,psci-0.2";
-		method = "smc";
+		remote_input_ao_pins: remote_input_ao {
+			mux {
+				groups = "remote_input_ao";
+				function = "remote_input_ao";
+			};
+		};
+
+		i2c_ao_pins: i2c_ao {
+			mux {
+				groups = "i2c_sck_ao",
+				       "i2c_sda_ao";
+				function = "i2c_ao";
+			};
+		};
+
+		pwm_ao_a_3_pins: pwm_ao_a_3 {
+			mux {
+				groups = "pwm_ao_a_3";
+				function = "pwm_ao_a_3";
+			};
+		};
+
+		pwm_ao_a_6_pins: pwm_ao_a_6 {
+			mux {
+				groups = "pwm_ao_a_6";
+				function = "pwm_ao_a_6";
+			};
+		};
+
+		pwm_ao_a_12_pins: pwm_ao_a_12 {
+			mux {
+				groups = "pwm_ao_a_12";
+				function = "pwm_ao_a_12";
+			};
+		};
+
+		pwm_ao_b_pins: pwm_ao_b {
+			mux {
+				groups = "pwm_ao_b";
+				function = "pwm_ao_b";
+			};
+		};
 	};
 
-	timer {
-		compatible = "arm,armv8-timer";
-		interrupts = <GIC_PPI 13
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
-			     <GIC_PPI 14
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
-			     <GIC_PPI 11
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
-			     <GIC_PPI 10
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>;
+	clkc_AO: clock-controller at 040 {
+		compatible = "amlogic,gxbb-aoclkc";
+		reg = <0x0 0x00040 0x0 0x4>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
 	};
 
-	xtal: xtal-clk {
-		compatible = "fixed-clock";
-		clock-frequency = <24000000>;
-		clock-output-names = "xtal";
-		#clock-cells = <0>;
+	pwm_ab_AO: pwm at 550 {
+		compatible = "amlogic,meson-gxbb-pwm";
+		reg = <0x0 0x0550 0x0 0x10>;
+		#pwm-cells = <3>;
+		status = "disabled";
 	};
 
-	soc {
-		compatible = "simple-bus";
+	i2c_AO: i2c at 500 {
+		compatible = "amlogic,meson-gxbb-i2c";
+		reg = <0x0 0x500 0x0 0x20>;
+		interrupts = <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&clkc CLKID_AO_I2C>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+};
+
+&periphs {
+	pinctrl_periphs: pinctrl at 4b0 {
+		compatible = "amlogic,meson-gxbb-periphs-pinctrl";
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
 
-		cbus: cbus at c1100000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xc1100000 0x0 0x100000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
-
-			reset: reset-controller at 4404 {
-				compatible = "amlogic,meson-gxbb-reset";
-				reg = <0x0 0x04404 0x0 0x20>;
-				#reset-cells = <1>;
-			};
-
-			uart_A: serial at 84c0 {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x84c0 0x0 0x14>;
-				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-
-			uart_B: serial at 84dc {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x84dc 0x0 0x14>;
-				interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-
-			uart_C: serial at 8700 {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x8700 0x0 0x14>;
-				interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-		};
-
-		gic: interrupt-controller at c4301000 {
-			compatible = "arm,gic-400";
-			reg = <0x0 0xc4301000 0 0x1000>,
-			      <0x0 0xc4302000 0 0x2000>,
-			      <0x0 0xc4304000 0 0x2000>,
-			      <0x0 0xc4306000 0 0x2000>;
-			interrupt-controller;
-			interrupts = <GIC_PPI 9
-				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
-			#interrupt-cells = <3>;
-			#address-cells = <0>;
-		};
-
-		aobus: aobus at c8100000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xc8100000 0x0 0x100000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
-
-			pinctrl_aobus: pinctrl at 14 {
-				compatible = "amlogic,meson-gxbb-aobus-pinctrl";
-				#address-cells = <2>;
-				#size-cells = <2>;
-				ranges;
-
-				gpio_ao: bank at 14 {
-					reg = <0x0 0x00014 0x0 0x8>,
-					      <0x0 0x0002c 0x0 0x4>,
-					      <0x0 0x00024 0x0 0x8>;
-					reg-names = "mux", "pull", "gpio";
-					gpio-controller;
-					#gpio-cells = <2>;
-				};
-
-				uart_ao_a_pins: uart_ao_a {
-					mux {
-						groups = "uart_tx_ao_a", "uart_rx_ao_a";
-						function = "uart_ao";
-					};
-				};
-			};
-
-			uart_AO: serial at 4c0 {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x004c0 0x0 0x14>;
-				interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-		};
-
-		periphs: periphs at c8834000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xc8834000 0x0 0x2000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>;
-
-			rng {
-				compatible = "amlogic,meson-rng";
-				reg = <0x0 0x0 0x0 0x4>;
-			};
-
-			pinctrl_periphs: pinctrl at 4b0 {
-				compatible = "amlogic,meson-gxbb-periphs-pinctrl";
-				#address-cells = <2>;
-				#size-cells = <2>;
-				ranges;
-
-				gpio: bank at 4b0 {
-					reg = <0x0 0x004b0 0x0 0x28>,
-					      <0x0 0x004e8 0x0 0x14>,
-					      <0x0 0x00120 0x0 0x14>,
-					      <0x0 0x00430 0x0 0x40>;
-					reg-names = "mux", "pull", "pull-enable", "gpio";
-					gpio-controller;
-					#gpio-cells = <2>;
-				};
-
-				emmc_pins: emmc {
-					mux {
-						groups = "emmc_nand_d07",
-						       "emmc_cmd",
-						       "emmc_clk";
-						function = "emmc";
-					};
-				};
-
-				sdcard_pins: sdcard {
-					mux {
-						groups = "sdcard_d0",
-						       "sdcard_d1",
-						       "sdcard_d2",
-						       "sdcard_d3",
-						       "sdcard_cmd",
-						       "sdcard_clk";
-						function = "sdcard";
-					};
-				};
-
-				uart_a_pins: uart_a {
-					mux {
-						groups = "uart_tx_a",
-						       "uart_rx_a";
-						function = "uart_a";
-					};
-				};
-
-				uart_b_pins: uart_b {
-					mux {
-						groups = "uart_tx_b",
-						       "uart_rx_b";
-						function = "uart_b";
-					};
-				};
-
-				uart_c_pins: uart_c {
-					mux {
-						groups = "uart_tx_c",
-						       "uart_rx_c";
-						function = "uart_c";
-					};
-				};
-
-				eth_pins: eth_c {
-					mux {
-						groups = "eth_mdio",
-						       "eth_mdc",
-						       "eth_clk_rx_clk",
-						       "eth_rx_dv",
-						       "eth_rxd0",
-						       "eth_rxd1",
-						       "eth_rxd2",
-						       "eth_rxd3",
-						       "eth_rgmii_tx_clk",
-						       "eth_tx_en",
-						       "eth_txd0",
-						       "eth_txd1",
-						       "eth_txd2",
-						       "eth_txd3";
-						function = "eth";
-					};
-				};
-			};
-		};
-
-		hiubus: hiubus at c883c000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xc883c000 0x0 0x2000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>;
-
-			clkc: clock-controller at 0 {
-				compatible = "amlogic,gxbb-clkc";
-				#clock-cells = <1>;
-				reg = <0x0 0x0 0x0 0x3db>;
-			};
-		};
-
-		apb: apb at d0000000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xd0000000 0x0 0x200000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
-		};
-
-		ethmac: ethernet at c9410000 {
-			compatible = "amlogic,meson6-dwmac", "snps,dwmac";
-			reg = <0x0 0xc9410000 0x0 0x10000
-			       0x0 0xc8834540 0x0 0x4>;
-			interrupts = <0 8 1>;
-			interrupt-names = "macirq";
-			clocks = <&xtal>;
-			clock-names = "stmmaceth";
-			phy-mode = "rgmii";
-			status = "disabled";
+		gpio: bank at 4b0 {
+			reg = <0x0 0x004b0 0x0 0x28>,
+			      <0x0 0x004e8 0x0 0x14>,
+			      <0x0 0x00120 0x0 0x14>,
+			      <0x0 0x00430 0x0 0x40>;
+			reg-names = "mux", "pull", "pull-enable", "gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		emmc_pins: emmc {
+			mux {
+				groups = "emmc_nand_d07",
+				       "emmc_cmd",
+				       "emmc_clk",
+				       "emmc_ds";
+				function = "emmc";
+			};
+		};
+
+		nor_pins: nor {
+			mux {
+				groups = "nor_d",
+				       "nor_q",
+				       "nor_c",
+				       "nor_cs";
+				function = "nor";
+			};
+		};
+
+		sdcard_pins: sdcard {
+			mux {
+				groups = "sdcard_d0",
+				       "sdcard_d1",
+				       "sdcard_d2",
+				       "sdcard_d3",
+				       "sdcard_cmd",
+				       "sdcard_clk";
+				function = "sdcard";
+			};
+		};
+
+		sdio_pins: sdio {
+			mux {
+				groups = "sdio_d0",
+				       "sdio_d1",
+				       "sdio_d2",
+				       "sdio_d3",
+				       "sdio_cmd",
+				       "sdio_clk";
+				function = "sdio";
+			};
+		};
+
+		sdio_irq_pins: sdio_irq {
+			mux {
+				groups = "sdio_irq";
+				function = "sdio";
+			};
+		};
+
+		uart_a_pins: uart_a {
+			mux {
+				groups = "uart_tx_a",
+				       "uart_rx_a";
+				function = "uart_a";
+			};
+		};
+
+		uart_a_cts_rts_pins: uart_a_cts_rts {
+			mux {
+				groups = "uart_cts_a",
+				       "uart_rts_a";
+				function = "uart_a";
+			};
+		};
+
+		uart_b_pins: uart_b {
+			mux {
+				groups = "uart_tx_b",
+				       "uart_rx_b";
+				function = "uart_b";
+			};
+		};
+
+		uart_b_cts_rts_pins: uart_b_cts_rts {
+			mux {
+				groups = "uart_cts_b",
+				       "uart_rts_b";
+				function = "uart_b";
+			};
+		};
+
+		uart_c_pins: uart_c {
+			mux {
+				groups = "uart_tx_c",
+				       "uart_rx_c";
+				function = "uart_c";
+			};
+		};
+
+		uart_c_cts_rts_pins: uart_c_cts_rts {
+			mux {
+				groups = "uart_cts_c",
+				       "uart_rts_c";
+				function = "uart_c";
+			};
+		};
+
+		i2c_a_pins: i2c_a {
+			mux {
+				groups = "i2c_sck_a",
+				       "i2c_sda_a";
+				function = "i2c_a";
+			};
+		};
+
+		i2c_b_pins: i2c_b {
+			mux {
+				groups = "i2c_sck_b",
+				       "i2c_sda_b";
+				function = "i2c_b";
+			};
+		};
+
+		i2c_c_pins: i2c_c {
+			mux {
+				groups = "i2c_sck_c",
+				       "i2c_sda_c";
+				function = "i2c_c";
+			};
+		};
+
+		eth_rgmii_pins: eth-rgmii {
+			mux {
+				groups = "eth_mdio",
+				       "eth_mdc",
+				       "eth_clk_rx_clk",
+				       "eth_rx_dv",
+				       "eth_rxd0",
+				       "eth_rxd1",
+				       "eth_rxd2",
+				       "eth_rxd3",
+				       "eth_rgmii_tx_clk",
+				       "eth_tx_en",
+				       "eth_txd0",
+				       "eth_txd1",
+				       "eth_txd2",
+				       "eth_txd3";
+				function = "eth";
+			};
+		};
+
+		eth_rmii_pins: eth-rmii {
+			mux {
+				groups = "eth_mdio",
+				       "eth_mdc",
+				       "eth_clk_rx_clk",
+				       "eth_rx_dv",
+				       "eth_rxd0",
+				       "eth_rxd1",
+				       "eth_tx_en",
+				       "eth_txd0",
+				       "eth_txd1";
+				function = "eth";
+			};
+		};
+
+		pwm_a_x_pins: pwm_a_x {
+			mux {
+				groups = "pwm_a_x";
+				function = "pwm_a_x";
+			};
+		};
+
+		pwm_a_y_pins: pwm_a_y {
+			mux {
+				groups = "pwm_a_y";
+				function = "pwm_a_y";
+			};
+		};
+
+		pwm_b_pins: pwm_b {
+			mux {
+				groups = "pwm_b";
+				function = "pwm_b";
+			};
+		};
+
+		pwm_d_pins: pwm_d {
+			mux {
+				groups = "pwm_d";
+				function = "pwm_d";
+			};
+		};
+
+		pwm_e_pins: pwm_e {
+			mux {
+				groups = "pwm_e";
+				function = "pwm_e";
+			};
+		};
+
+		pwm_f_x_pins: pwm_f_x {
+			mux {
+				groups = "pwm_f_x";
+				function = "pwm_f_x";
+			};
+		};
+
+		pwm_f_y_pins: pwm_f_y {
+			mux {
+				groups = "pwm_f_y";
+				function = "pwm_f_y";
+			};
+		};
+
+		hdmi_hpd_pins: hdmi_hpd {
+			mux {
+				groups = "hdmi_hpd";
+				function = "hdmi_hpd";
+			};
+		};
+
+		hdmi_i2c_pins: hdmi_i2c {
+			mux {
+				groups = "hdmi_sda", "hdmi_scl";
+				function = "hdmi_i2c";
+			};
 		};
 	};
 };
+
+&hiubus {
+	clkc: clock-controller at 0 {
+		compatible = "amlogic,gxbb-clkc";
+		#clock-cells = <1>;
+		reg = <0x0 0x0 0x0 0x3db>;
+	};
+};
+
+&i2c_A {
+	clocks = <&clkc CLKID_I2C>;
+};
+
+&i2c_B {
+	clocks = <&clkc CLKID_I2C>;
+};
+
+&i2c_C {
+	clocks = <&clkc CLKID_I2C>;
+};
+
+&sd_emmc_a {
+	clocks = <&clkc CLKID_SD_EMMC_A>,
+		 <&xtal>,
+		 <&clkc CLKID_FCLK_DIV2>;
+	clock-names = "core", "clkin0", "clkin1";
+};
+
+&sd_emmc_b {
+	clocks = <&clkc CLKID_SD_EMMC_B>,
+		 <&xtal>,
+		 <&clkc CLKID_FCLK_DIV2>;
+	clock-names = "core", "clkin0", "clkin1";
+};
+
+&sd_emmc_c {
+	clocks = <&clkc CLKID_SD_EMMC_C>,
+		 <&xtal>,
+		 <&clkc CLKID_FCLK_DIV2>;
+	clock-names = "core", "clkin0", "clkin1";
+};
+
+&vpu {
+	compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu";
+};
include/dt-bindings/clock/gxbb-aoclkc.h new file +66 -0
new file mode 100644
index 0000000..3175148
@@ -0,0 +1,66 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public 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; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DT_BINDINGS_CLOCK_AMLOGIC_MESON_GXBB_AOCLK
+#define DT_BINDINGS_CLOCK_AMLOGIC_MESON_GXBB_AOCLK
+
+#define CLKID_AO_REMOTE		0
+#define CLKID_AO_I2C_MASTER	1
+#define CLKID_AO_I2C_SLAVE	2
+#define CLKID_AO_UART1		3
+#define CLKID_AO_UART2		4
+#define CLKID_AO_IR_BLASTER	5
+
+#endif
include/dt-bindings/clock/gxbb-clkc.h new file +34 -0
new file mode 100644
index 0000000..692846c
@@ -0,0 +1,34 @@
+/*
+ * GXBB clock tree IDs
+ */
+
+#ifndef __GXBB_CLKC_H
+#define __GXBB_CLKC_H
+
+#define CLKID_CPUCLK		1
+#define CLKID_HDMI_PLL		2
+#define CLKID_FCLK_DIV2		4
+#define CLKID_FCLK_DIV3		5
+#define CLKID_FCLK_DIV4		6
+#define CLKID_CLK81		12
+#define CLKID_MPLL2		15
+#define CLKID_SPI		34
+#define CLKID_I2C		22
+#define CLKID_SAR_ADC		23
+#define CLKID_ETH		36
+#define CLKID_USB0		50
+#define CLKID_USB1		51
+#define CLKID_USB		55
+#define CLKID_HDMI_PCLK		63
+#define CLKID_USB1_DDR_BRIDGE	64
+#define CLKID_USB0_DDR_BRIDGE	65
+#define CLKID_SANA		69
+#define CLKID_GCLK_VENCI_INT0	77
+#define CLKID_AO_I2C		93
+#define CLKID_SD_EMMC_A		94
+#define CLKID_SD_EMMC_B		95
+#define CLKID_SD_EMMC_C		96
+#define CLKID_SAR_ADC_CLK	97
+#define CLKID_SAR_ADC_SEL	98
+
+#endif /* __GXBB_CLKC_H */
include/dt-bindings/reset/gxbb-aoclkc.h new file +66 -0
new file mode 100644
index 0000000..9e3fd60
@@ -0,0 +1,66 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public 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; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DT_BINDINGS_RESET_AMLOGIC_MESON_GXBB_AOCLK
+#define DT_BINDINGS_RESET_AMLOGIC_MESON_GXBB_AOCLK
+
+#define RESET_AO_REMOTE		0
+#define RESET_AO_I2C_MASTER	1
+#define RESET_AO_I2C_SLAVE	2
+#define RESET_AO_UART1		3
+#define RESET_AO_UART2		4
+#define RESET_AO_IR_BLASTER	5
+
+#endif
#3 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

In reply to Heiner Kallweit

From: Carlo Caione <[email protected]>
This driver implements MMC support on Meson GX (S905) based systems. It's based on Carlo Caione's work, changes:
- BLK support added
- general refactoring

---
v6:
- remove DM_MMC_OPS from Kconfig dependencies
- address two minor review comments of Jaehoon
v7:
- rebased

---
 arch/arm/include/asm/arch-meson/sd_emmc.h |  89 +++++++++
 drivers/mmc/Kconfig                       |   6 +
 drivers/mmc/Makefile                      |   1 +
 drivers/mmc/meson_gx_mmc.c                | 291 ++++++++++++++++++++++++++++++
 4 files changed, 387 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-meson/sd_emmc.h
 create mode 100644 drivers/mmc/meson_gx_mmc.c
arch/arm/include/asm/arch-meson/sd_emmc.h new file +89 -0
new file mode 100644
index 0000000..a09e034
@@ -0,0 +1,89 @@
+/*
+ * (C) Copyright 2016 Carlo Caione <[email protected]>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __SD_EMMC_H__
+#define __SD_EMMC_H__
+
+#include <mmc.h>
+
+#define SDIO_PORT_A			0
+#define SDIO_PORT_B			1
+#define SDIO_PORT_C			2
+
+#define SD_EMMC_CLKSRC_24M		24000000	/* 24 MHz */
+#define SD_EMMC_CLKSRC_DIV2		1000000000	/* 1 GHz */
+
+#define MESON_SD_EMMC_CLOCK		0x00
+#define   CLK_MAX_DIV			63
+#define   CLK_SRC_24M			(0 << 6)
+#define   CLK_SRC_DIV2			(1 << 6)
+#define   CLK_CO_PHASE_000		(0 << 8)
+#define   CLK_CO_PHASE_090		(1 << 8)
+#define   CLK_CO_PHASE_180		(2 << 8)
+#define   CLK_CO_PHASE_270		(3 << 8)
+#define   CLK_TX_PHASE_000		(0 << 10)
+#define   CLK_TX_PHASE_090		(1 << 10)
+#define   CLK_TX_PHASE_180		(2 << 10)
+#define   CLK_TX_PHASE_270		(3 << 10)
+#define   CLK_ALWAYS_ON			BIT(24)
+
+#define MESON_SD_EMMC_CFG		0x44
+#define   CFG_BUS_WIDTH_MASK		GENMASK(1, 0)
+#define   CFG_BUS_WIDTH_1		0
+#define   CFG_BUS_WIDTH_4		1
+#define   CFG_BUS_WIDTH_8		2
+#define   CFG_BL_LEN_MASK		GENMASK(7, 4)
+#define   CFG_BL_LEN_SHIFT		4
+#define   CFG_BL_LEN_512		(9 << 4)
+#define   CFG_RESP_TIMEOUT_MASK		GENMASK(11, 8)
+#define   CFG_RESP_TIMEOUT_256		(8 << 8)
+#define   CFG_RC_CC_MASK		GENMASK(15, 12)
+#define   CFG_RC_CC_16			(4 << 12)
+#define   CFG_SDCLK_ALWAYS_ON		BIT(18)
+#define   CFG_AUTO_CLK			BIT(23)
+
+#define MESON_SD_EMMC_STATUS		0x48
+#define   STATUS_MASK			GENMASK(15, 0)
+#define   STATUS_ERR_MASK		GENMASK(12, 0)
+#define   STATUS_RXD_ERR_MASK		GENMASK(7, 0)
+#define   STATUS_TXD_ERR		BIT(8)
+#define   STATUS_DESC_ERR		BIT(9)
+#define   STATUS_RESP_ERR		BIT(10)
+#define   STATUS_RESP_TIMEOUT		BIT(11)
+#define   STATUS_DESC_TIMEOUT		BIT(12)
+#define   STATUS_END_OF_CHAIN		BIT(13)
+
+#define MESON_SD_EMMC_IRQ_EN		0x4c
+
+#define MESON_SD_EMMC_CMD_CFG		0x50
+#define   CMD_CFG_LENGTH_MASK		GENMASK(8, 0)
+#define   CMD_CFG_BLOCK_MODE		BIT(9)
+#define   CMD_CFG_R1B			BIT(10)
+#define   CMD_CFG_END_OF_CHAIN		BIT(11)
+#define   CMD_CFG_TIMEOUT_4S		(12 << 12)
+#define   CMD_CFG_NO_RESP		BIT(16)
+#define   CMD_CFG_DATA_IO		BIT(18)
+#define   CMD_CFG_DATA_WR		BIT(19)
+#define   CMD_CFG_RESP_NOCRC		BIT(20)
+#define   CMD_CFG_RESP_128		BIT(21)
+#define   CMD_CFG_CMD_INDEX_SHIFT	24
+#define   CMD_CFG_OWNER			BIT(31)
+
+#define MESON_SD_EMMC_CMD_ARG		0x54
+#define MESON_SD_EMMC_CMD_DAT		0x58
+#define MESON_SD_EMMC_CMD_RSP		0x5c
+#define MESON_SD_EMMC_CMD_RSP1		0x60
+#define MESON_SD_EMMC_CMD_RSP2		0x64
+#define MESON_SD_EMMC_CMD_RSP3		0x68
+
+struct meson_mmc_platdata {
+	struct mmc_config cfg;
+	struct mmc mmc;
+	void *regbase;
+	void *w_buf;
+};
+
+#endif
drivers/mmc/Kconfig +6 -0
index 560391f..077b184 100644
@@ -105,6 +105,12 @@ config MMC_DW_SOCFPGA
 	  Synopsys DesignWare Memory Card Interface driver. Select this option
 	  for platforms based on Altera SOCFPGA.
 
+config MMC_MESON_GX
+	bool "Meson GX EMMC controller support"
+	depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_MESON
+	help
+	 Support for EMMC host controller on Meson GX ARM SoCs platform (S905)
+
 config MMC_MXC
 	bool "Freescale i.MX21/27/31 or MPC512x Multimedia Card support"
 	help
drivers/mmc/Makefile +1 -0
index 6a26a52..a61a9e9 100644
@@ -29,6 +29,7 @@ ifdef CONFIG_SUPPORT_EMMC_BOOT
 obj-$(CONFIG_GENERIC_MMC) += mmc_boot.o
 endif
 obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
+obj-$(CONFIG_MMC_MESON_GX) += meson_gx_mmc.o
 obj-$(CONFIG_MMC_SPI) += mmc_spi.o
 obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o
 obj-$(CONFIG_MMC_OMAP_HS)		+= omap_hsmmc.o
drivers/mmc/meson_gx_mmc.c new file +291 -0

291 lines not on this page · raw message

Signature · 1 line
2.12.2
#4 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Quoted 9 lines · Heiner Kallweit

From: Carlo Caione <[email protected]>
This driver implements MMC support on Meson GX (S905) based systems. It's based on Carlo Caione's work, changes:
- BLK support added
- general refactoring

Tested on odroid-c2, loads and boots kernel + initramfs + devicetree.

Thanks!

live well,
vagrant

Quoted 426 lines

---
v6:
- remove DM_MMC_OPS from Kconfig dependencies
- address two minor review comments of Jaehoon
v7:
- rebased

---
 arch/arm/include/asm/arch-meson/sd_emmc.h |  89 +++++++++
 drivers/mmc/Kconfig                       |   6 +
 drivers/mmc/Makefile                      |   1 +
 drivers/mmc/meson_gx_mmc.c                | 291 ++++++++++++++++++++++++++++++
 4 files changed, 387 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-meson/sd_emmc.h
 create mode 100644 drivers/mmc/meson_gx_mmc.c
arch/arm/include/asm/arch-meson/sd_emmc.h new file +89 -0
new file mode 100644
index 0000000..a09e034
@@ -0,0 +1,89 @@
+/*
+ * (C) Copyright 2016 Carlo Caione <[email protected]>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __SD_EMMC_H__
+#define __SD_EMMC_H__
+
+#include <mmc.h>
+
+#define SDIO_PORT_A			0
+#define SDIO_PORT_B			1
+#define SDIO_PORT_C			2
+
+#define SD_EMMC_CLKSRC_24M		24000000	/* 24 MHz */
+#define SD_EMMC_CLKSRC_DIV2		1000000000	/* 1 GHz */
+
+#define MESON_SD_EMMC_CLOCK		0x00
+#define   CLK_MAX_DIV			63
+#define   CLK_SRC_24M			(0 << 6)
+#define   CLK_SRC_DIV2			(1 << 6)
+#define   CLK_CO_PHASE_000		(0 << 8)
+#define   CLK_CO_PHASE_090		(1 << 8)
+#define   CLK_CO_PHASE_180		(2 << 8)
+#define   CLK_CO_PHASE_270		(3 << 8)
+#define   CLK_TX_PHASE_000		(0 << 10)
+#define   CLK_TX_PHASE_090		(1 << 10)
+#define   CLK_TX_PHASE_180		(2 << 10)
+#define   CLK_TX_PHASE_270		(3 << 10)
+#define   CLK_ALWAYS_ON			BIT(24)
+
+#define MESON_SD_EMMC_CFG		0x44
+#define   CFG_BUS_WIDTH_MASK		GENMASK(1, 0)
+#define   CFG_BUS_WIDTH_1		0
+#define   CFG_BUS_WIDTH_4		1
+#define   CFG_BUS_WIDTH_8		2
+#define   CFG_BL_LEN_MASK		GENMASK(7, 4)
+#define   CFG_BL_LEN_SHIFT		4
+#define   CFG_BL_LEN_512		(9 << 4)
+#define   CFG_RESP_TIMEOUT_MASK		GENMASK(11, 8)
+#define   CFG_RESP_TIMEOUT_256		(8 << 8)
+#define   CFG_RC_CC_MASK		GENMASK(15, 12)
+#define   CFG_RC_CC_16			(4 << 12)
+#define   CFG_SDCLK_ALWAYS_ON		BIT(18)
+#define   CFG_AUTO_CLK			BIT(23)
+
+#define MESON_SD_EMMC_STATUS		0x48
+#define   STATUS_MASK			GENMASK(15, 0)
+#define   STATUS_ERR_MASK		GENMASK(12, 0)
+#define   STATUS_RXD_ERR_MASK		GENMASK(7, 0)
+#define   STATUS_TXD_ERR		BIT(8)
+#define   STATUS_DESC_ERR		BIT(9)
+#define   STATUS_RESP_ERR		BIT(10)
+#define   STATUS_RESP_TIMEOUT		BIT(11)
+#define   STATUS_DESC_TIMEOUT		BIT(12)
+#define   STATUS_END_OF_CHAIN		BIT(13)
+
+#define MESON_SD_EMMC_IRQ_EN		0x4c
+
+#define MESON_SD_EMMC_CMD_CFG		0x50
+#define   CMD_CFG_LENGTH_MASK		GENMASK(8, 0)
+#define   CMD_CFG_BLOCK_MODE		BIT(9)
+#define   CMD_CFG_R1B			BIT(10)
+#define   CMD_CFG_END_OF_CHAIN		BIT(11)
+#define   CMD_CFG_TIMEOUT_4S		(12 << 12)
+#define   CMD_CFG_NO_RESP		BIT(16)
+#define   CMD_CFG_DATA_IO		BIT(18)
+#define   CMD_CFG_DATA_WR		BIT(19)
+#define   CMD_CFG_RESP_NOCRC		BIT(20)
+#define   CMD_CFG_RESP_128		BIT(21)
+#define   CMD_CFG_CMD_INDEX_SHIFT	24
+#define   CMD_CFG_OWNER			BIT(31)
+
+#define MESON_SD_EMMC_CMD_ARG		0x54
+#define MESON_SD_EMMC_CMD_DAT		0x58
+#define MESON_SD_EMMC_CMD_RSP		0x5c
+#define MESON_SD_EMMC_CMD_RSP1		0x60
+#define MESON_SD_EMMC_CMD_RSP2		0x64
+#define MESON_SD_EMMC_CMD_RSP3		0x68
+
+struct meson_mmc_platdata {
+	struct mmc_config cfg;
+	struct mmc mmc;
+	void *regbase;
+	void *w_buf;
+};
+
+#endif
drivers/mmc/Kconfig +6 -0
index 560391f..077b184 100644
@@ -105,6 +105,12 @@ config MMC_DW_SOCFPGA
 	  Synopsys DesignWare Memory Card Interface driver. Select this option
 	  for platforms based on Altera SOCFPGA.
 
+config MMC_MESON_GX
+	bool "Meson GX EMMC controller support"
+	depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_MESON
+	help
+	 Support for EMMC host controller on Meson GX ARM SoCs platform (S905)
+
 config MMC_MXC
 	bool "Freescale i.MX21/27/31 or MPC512x Multimedia Card support"
 	help
drivers/mmc/Makefile +1 -0
index 6a26a52..a61a9e9 100644
@@ -29,6 +29,7 @@ ifdef CONFIG_SUPPORT_EMMC_BOOT
 obj-$(CONFIG_GENERIC_MMC) += mmc_boot.o
 endif
 obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
+obj-$(CONFIG_MMC_MESON_GX) += meson_gx_mmc.o
 obj-$(CONFIG_MMC_SPI) += mmc_spi.o
 obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o
 obj-$(CONFIG_MMC_OMAP_HS)		+= omap_hsmmc.o
drivers/mmc/meson_gx_mmc.c new file +281 -0
new file mode 100644
index 0000000..8e28ab7
@@ -0,0 +1,291 @@
+/*
+ * (C) Copyright 2016 Carlo Caione <[email protected]>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <asm/io.h>
+#include <asm/arch/sd_emmc.h>
+#include <dm/device.h>
+#include <linux/log2.h>
+
+static inline void *get_regbase(const struct mmc *mmc)
+{
+	struct meson_mmc_platdata *pdata = mmc->priv;
+
+	return pdata->regbase;
+}
+
+static inline uint32_t meson_read(struct mmc *mmc, int offset)
+{
+	return readl(get_regbase(mmc) + offset);
+}
+
+static inline void meson_write(struct mmc *mmc, uint32_t val, int offset)
+{
+	writel(val, get_regbase(mmc) + offset);
+}
+
+static void meson_mmc_config_clock(struct mmc *mmc)
+{
+	uint32_t meson_mmc_clk = 0;
+	unsigned int clk, clk_src, clk_div;
+
+	/* 1GHz / CLK_MAX_DIV = 15,9 MHz */
+	if (mmc->clock > 16000000) {
+		clk = SD_EMMC_CLKSRC_DIV2;
+		clk_src = CLK_SRC_DIV2;
+	} else {
+		clk = SD_EMMC_CLKSRC_24M;
+		clk_src = CLK_SRC_24M;
+	}
+	clk_div = DIV_ROUND_UP(clk, mmc->clock);
+
+	/* 180 phase core clock */
+	meson_mmc_clk |= CLK_CO_PHASE_180;
+
+	/* 180 phase tx clock */
+	meson_mmc_clk |= CLK_TX_PHASE_000;
+
+	/* clock settings */
+	meson_mmc_clk |= clk_src;
+	meson_mmc_clk |= clk_div;
+
+	meson_write(mmc, meson_mmc_clk, MESON_SD_EMMC_CLOCK);
+}
+
+static int meson_dm_mmc_set_ios(struct udevice *dev)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	uint32_t meson_mmc_cfg;
+
+	meson_mmc_config_clock(mmc);
+
+	meson_mmc_cfg = meson_read(mmc, MESON_SD_EMMC_CFG);
+
+	meson_mmc_cfg &= ~CFG_BUS_WIDTH_MASK;
+	if (mmc->bus_width == 1)
+		meson_mmc_cfg |= CFG_BUS_WIDTH_1;
+	else if (mmc->bus_width == 4)
+		meson_mmc_cfg |= CFG_BUS_WIDTH_4;
+	else if (mmc->bus_width == 8)
+		meson_mmc_cfg |= CFG_BUS_WIDTH_8;
+	else
+		return -EINVAL;
+
+	/* 512 bytes block length */
+	meson_mmc_cfg &= ~CFG_BL_LEN_MASK;
+	meson_mmc_cfg |= CFG_BL_LEN_512;
+
+	/* Response timeout 256 clk */
+	meson_mmc_cfg &= ~CFG_RESP_TIMEOUT_MASK;
+	meson_mmc_cfg |= CFG_RESP_TIMEOUT_256;
+
+	/* Command-command gap 16 clk */
+	meson_mmc_cfg &= ~CFG_RC_CC_MASK;
+	meson_mmc_cfg |= CFG_RC_CC_16;
+
+	meson_write(mmc, meson_mmc_cfg, MESON_SD_EMMC_CFG);
+
+	return 0;
+}
+
+static void meson_mmc_setup_cmd(struct mmc *mmc, struct mmc_data *data,
+				struct mmc_cmd *cmd)
+{
+	uint32_t meson_mmc_cmd = 0, cfg;
+
+	meson_mmc_cmd |= cmd->cmdidx << CMD_CFG_CMD_INDEX_SHIFT;
+
+	if (cmd->resp_type & MMC_RSP_PRESENT) {
+		if (cmd->resp_type & MMC_RSP_136)
+			meson_mmc_cmd |= CMD_CFG_RESP_128;
+
+		if (cmd->resp_type & MMC_RSP_BUSY)
+			meson_mmc_cmd |= CMD_CFG_R1B;
+
+		if (!(cmd->resp_type & MMC_RSP_CRC))
+			meson_mmc_cmd |= CMD_CFG_RESP_NOCRC;
+	} else {
+		meson_mmc_cmd |= CMD_CFG_NO_RESP;
+	}
+
+	if (data) {
+		cfg = meson_read(mmc, MESON_SD_EMMC_CFG);
+		cfg &= ~CFG_BL_LEN_MASK;
+		cfg |= ilog2(data->blocksize) << CFG_BL_LEN_SHIFT;
+		meson_write(mmc, cfg, MESON_SD_EMMC_CFG);
+
+		if (data->flags == MMC_DATA_WRITE)
+			meson_mmc_cmd |= CMD_CFG_DATA_WR;
+
+		meson_mmc_cmd |= CMD_CFG_DATA_IO | CMD_CFG_BLOCK_MODE |
+				 data->blocks;
+	}
+
+	meson_mmc_cmd |= CMD_CFG_TIMEOUT_4S | CMD_CFG_OWNER |
+			 CMD_CFG_END_OF_CHAIN;
+
+	meson_write(mmc, meson_mmc_cmd, MESON_SD_EMMC_CMD_CFG);
+}
+
+static void meson_mmc_setup_addr(struct mmc *mmc, struct mmc_data *data)
+{
+	struct meson_mmc_platdata *pdata = mmc->priv;
+	unsigned int data_size;
+	uint32_t data_addr = 0;
+
+	if (data) {
+		data_size = data->blocks * data->blocksize;
+
+		if (data->flags == MMC_DATA_READ) {
+			data_addr = (ulong) data->dest;
+			invalidate_dcache_range(data_addr,
+						data_addr + data_size);
+		} else {
+			pdata->w_buf = calloc(data_size, sizeof(char));
+			data_addr = (ulong) pdata->w_buf;
+			memcpy(pdata->w_buf, data->src, data_size);
+			flush_dcache_range(data_addr, data_addr + data_size);
+		}
+	}
+
+	meson_write(mmc, data_addr, MESON_SD_EMMC_CMD_DAT);
+}
+
+static void meson_mmc_read_response(struct mmc *mmc, struct mmc_cmd *cmd)
+{
+	if (cmd->resp_type & MMC_RSP_136) {
+		cmd->response[0] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP3);
+		cmd->response[1] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP2);
+		cmd->response[2] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP1);
+		cmd->response[3] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP);
+	} else {
+		cmd->response[0] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP);
+	}
+}
+
+static int meson_dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+				 struct mmc_data *data)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	struct meson_mmc_platdata *pdata = mmc->priv;
+	uint32_t status;
+	ulong start;
+	int ret = 0;
+
+	/* max block size supported by chip is 512 byte */
+	if (data && data->blocksize > 512)
+		return -EINVAL;
+
+	meson_mmc_setup_cmd(mmc, data, cmd);
+	meson_mmc_setup_addr(mmc, data);
+
+	meson_write(mmc, cmd->cmdarg, MESON_SD_EMMC_CMD_ARG);
+
+	/* use 10s timeout */
+	start = get_timer(0);
+	do {
+		status = meson_read(mmc, MESON_SD_EMMC_STATUS);
+	} while(!(status & STATUS_END_OF_CHAIN) && get_timer(start) < 10000);
+
+	if (!(status & STATUS_END_OF_CHAIN))
+		ret = -ETIMEDOUT;
+	else if (status & STATUS_RESP_TIMEOUT)
+		ret = -ETIMEDOUT;
+	else if (status & STATUS_ERR_MASK)
+		ret = -EIO;
+
+	meson_mmc_read_response(mmc, cmd);
+
+	if (data && data->flags == MMC_DATA_WRITE)
+		free(pdata->w_buf);
+
+	/* reset status bits */
+	meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS);
+
+	return ret;
+}
+
+static const struct dm_mmc_ops meson_dm_mmc_ops = {
+	.send_cmd = meson_dm_mmc_send_cmd,
+	.set_ios = meson_dm_mmc_set_ios,
+};
+
+static int meson_mmc_ofdata_to_platdata(struct udevice *dev)
+{
+	struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
+	fdt_addr_t addr;
+
+	addr = dev_get_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	pdata->regbase = (void *)addr;
+
+	return 0;
+}
+
+static int meson_mmc_probe(struct udevice *dev)
+{
+	struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct mmc *mmc = &pdata->mmc;
+	struct mmc_config *cfg = &pdata->cfg;
+	uint32_t val;
+
+	cfg->voltages = MMC_VDD_33_34 | MMC_VDD_32_33 |
+			MMC_VDD_31_32 | MMC_VDD_165_195;
+	cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT |
+			MMC_MODE_HS_52MHz | MMC_MODE_HS;
+	cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
+	cfg->f_max = 100000000; /* 100 MHz */
+	cfg->b_max = 256; /* max 256 blocks */
+	cfg->name = dev->name;
+
+	mmc->priv = pdata;
+	upriv->mmc = mmc;
+
+	mmc_set_clock(mmc, cfg->f_min);
+
+	/* reset all status bits */
+	meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS);
+
+	/* disable interrupts */
+	meson_write(mmc, 0, MESON_SD_EMMC_IRQ_EN);
+
+	/* enable auto clock mode */
+	val = meson_read(mmc, MESON_SD_EMMC_CFG);
+	val &= ~CFG_SDCLK_ALWAYS_ON;
+	val |= CFG_AUTO_CLK;
+	meson_write(mmc, val, MESON_SD_EMMC_CFG);
+
+	return 0;
+}
+
+int meson_mmc_bind(struct udevice *dev)
+{
+	struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
+
+	return mmc_bind(dev, &pdata->mmc, &pdata->cfg);
+}
+
+static const struct udevice_id meson_mmc_match[] = {
+	{ .compatible = "amlogic,meson-gx-mmc" },
+	{ /* sentinel */ }
+};
+

drivers/mmc/meson_gx_mmc.c line 291

Quoted 10 lines
drivers/mmc/meson_gx_mmc.c new file +10 -0
+U_BOOT_DRIVER(meson_mmc) = {
+	.name = "meson_gx_mmc",
+	.id = UCLASS_MMC,
+	.of_match = meson_mmc_match,
+	.ops = &meson_dm_mmc_ops,
+	.probe = meson_mmc_probe,
+	.bind = meson_mmc_bind,
+	.ofdata_to_platdata = meson_mmc_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct meson_mmc_platdata),
+};

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170412/4e3feee6/attachment.sig>

#5 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

In reply to Heiner Kallweit
Quoted 9 lines · Heiner Kallweit

From: Carlo Caione <[email protected]>
This driver implements MMC support on Meson GX (S905) based systems. It's based on Carlo Caione's work, changes:
- BLK support added
- general refactoring

Applied to u-boot-mmc. Thanks!

Best Regards,
Jaehoon Chung

Quoted 437 lines

---
v6:
- remove DM_MMC_OPS from Kconfig dependencies
- address two minor review comments of Jaehoon
v7:
- rebased

---
 arch/arm/include/asm/arch-meson/sd_emmc.h |  89 +++++++++
 drivers/mmc/Kconfig                       |   6 +
 drivers/mmc/Makefile                      |   1 +
 drivers/mmc/meson_gx_mmc.c                | 291 ++++++++++++++++++++++++++++++
 4 files changed, 387 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-meson/sd_emmc.h
 create mode 100644 drivers/mmc/meson_gx_mmc.c
arch/arm/include/asm/arch-meson/sd_emmc.h new file +89 -0
new file mode 100644
index 0000000..a09e034
@@ -0,0 +1,89 @@
+/*
+ * (C) Copyright 2016 Carlo Caione <[email protected]>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __SD_EMMC_H__
+#define __SD_EMMC_H__
+
+#include <mmc.h>
+
+#define SDIO_PORT_A			0
+#define SDIO_PORT_B			1
+#define SDIO_PORT_C			2
+
+#define SD_EMMC_CLKSRC_24M		24000000	/* 24 MHz */
+#define SD_EMMC_CLKSRC_DIV2		1000000000	/* 1 GHz */
+
+#define MESON_SD_EMMC_CLOCK		0x00
+#define   CLK_MAX_DIV			63
+#define   CLK_SRC_24M			(0 << 6)
+#define   CLK_SRC_DIV2			(1 << 6)
+#define   CLK_CO_PHASE_000		(0 << 8)
+#define   CLK_CO_PHASE_090		(1 << 8)
+#define   CLK_CO_PHASE_180		(2 << 8)
+#define   CLK_CO_PHASE_270		(3 << 8)
+#define   CLK_TX_PHASE_000		(0 << 10)
+#define   CLK_TX_PHASE_090		(1 << 10)
+#define   CLK_TX_PHASE_180		(2 << 10)
+#define   CLK_TX_PHASE_270		(3 << 10)
+#define   CLK_ALWAYS_ON			BIT(24)
+
+#define MESON_SD_EMMC_CFG		0x44
+#define   CFG_BUS_WIDTH_MASK		GENMASK(1, 0)
+#define   CFG_BUS_WIDTH_1		0
+#define   CFG_BUS_WIDTH_4		1
+#define   CFG_BUS_WIDTH_8		2
+#define   CFG_BL_LEN_MASK		GENMASK(7, 4)
+#define   CFG_BL_LEN_SHIFT		4
+#define   CFG_BL_LEN_512		(9 << 4)
+#define   CFG_RESP_TIMEOUT_MASK		GENMASK(11, 8)
+#define   CFG_RESP_TIMEOUT_256		(8 << 8)
+#define   CFG_RC_CC_MASK		GENMASK(15, 12)
+#define   CFG_RC_CC_16			(4 << 12)
+#define   CFG_SDCLK_ALWAYS_ON		BIT(18)
+#define   CFG_AUTO_CLK			BIT(23)
+
+#define MESON_SD_EMMC_STATUS		0x48
+#define   STATUS_MASK			GENMASK(15, 0)
+#define   STATUS_ERR_MASK		GENMASK(12, 0)
+#define   STATUS_RXD_ERR_MASK		GENMASK(7, 0)
+#define   STATUS_TXD_ERR		BIT(8)
+#define   STATUS_DESC_ERR		BIT(9)
+#define   STATUS_RESP_ERR		BIT(10)
+#define   STATUS_RESP_TIMEOUT		BIT(11)
+#define   STATUS_DESC_TIMEOUT		BIT(12)
+#define   STATUS_END_OF_CHAIN		BIT(13)
+
+#define MESON_SD_EMMC_IRQ_EN		0x4c
+
+#define MESON_SD_EMMC_CMD_CFG		0x50
+#define   CMD_CFG_LENGTH_MASK		GENMASK(8, 0)
+#define   CMD_CFG_BLOCK_MODE		BIT(9)
+#define   CMD_CFG_R1B			BIT(10)
+#define   CMD_CFG_END_OF_CHAIN		BIT(11)
+#define   CMD_CFG_TIMEOUT_4S		(12 << 12)
+#define   CMD_CFG_NO_RESP		BIT(16)
+#define   CMD_CFG_DATA_IO		BIT(18)
+#define   CMD_CFG_DATA_WR		BIT(19)
+#define   CMD_CFG_RESP_NOCRC		BIT(20)
+#define   CMD_CFG_RESP_128		BIT(21)
+#define   CMD_CFG_CMD_INDEX_SHIFT	24
+#define   CMD_CFG_OWNER			BIT(31)
+
+#define MESON_SD_EMMC_CMD_ARG		0x54
+#define MESON_SD_EMMC_CMD_DAT		0x58
+#define MESON_SD_EMMC_CMD_RSP		0x5c
+#define MESON_SD_EMMC_CMD_RSP1		0x60
+#define MESON_SD_EMMC_CMD_RSP2		0x64
+#define MESON_SD_EMMC_CMD_RSP3		0x68
+
+struct meson_mmc_platdata {
+	struct mmc_config cfg;
+	struct mmc mmc;
+	void *regbase;
+	void *w_buf;
+};
+
+#endif
drivers/mmc/Kconfig +6 -0
index 560391f..077b184 100644
@@ -105,6 +105,12 @@ config MMC_DW_SOCFPGA
 	  Synopsys DesignWare Memory Card Interface driver. Select this option
 	  for platforms based on Altera SOCFPGA.
 
+config MMC_MESON_GX
+	bool "Meson GX EMMC controller support"
+	depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_MESON
+	help
+	 Support for EMMC host controller on Meson GX ARM SoCs platform (S905)
+
 config MMC_MXC
 	bool "Freescale i.MX21/27/31 or MPC512x Multimedia Card support"
 	help
drivers/mmc/Makefile +1 -0
index 6a26a52..a61a9e9 100644
@@ -29,6 +29,7 @@ ifdef CONFIG_SUPPORT_EMMC_BOOT
 obj-$(CONFIG_GENERIC_MMC) += mmc_boot.o
 endif
 obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
+obj-$(CONFIG_MMC_MESON_GX) += meson_gx_mmc.o
 obj-$(CONFIG_MMC_SPI) += mmc_spi.o
 obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o
 obj-$(CONFIG_MMC_OMAP_HS)		+= omap_hsmmc.o
drivers/mmc/meson_gx_mmc.c new file +291 -0
new file mode 100644
index 0000000..8e28ab7
@@ -0,0 +1,291 @@
+/*
+ * (C) Copyright 2016 Carlo Caione <[email protected]>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <asm/io.h>
+#include <asm/arch/sd_emmc.h>
+#include <dm/device.h>
+#include <linux/log2.h>
+
+static inline void *get_regbase(const struct mmc *mmc)
+{
+	struct meson_mmc_platdata *pdata = mmc->priv;
+
+	return pdata->regbase;
+}
+
+static inline uint32_t meson_read(struct mmc *mmc, int offset)
+{
+	return readl(get_regbase(mmc) + offset);
+}
+
+static inline void meson_write(struct mmc *mmc, uint32_t val, int offset)
+{
+	writel(val, get_regbase(mmc) + offset);
+}
+
+static void meson_mmc_config_clock(struct mmc *mmc)
+{
+	uint32_t meson_mmc_clk = 0;
+	unsigned int clk, clk_src, clk_div;
+
+	/* 1GHz / CLK_MAX_DIV = 15,9 MHz */
+	if (mmc->clock > 16000000) {
+		clk = SD_EMMC_CLKSRC_DIV2;
+		clk_src = CLK_SRC_DIV2;
+	} else {
+		clk = SD_EMMC_CLKSRC_24M;
+		clk_src = CLK_SRC_24M;
+	}
+	clk_div = DIV_ROUND_UP(clk, mmc->clock);
+
+	/* 180 phase core clock */
+	meson_mmc_clk |= CLK_CO_PHASE_180;
+
+	/* 180 phase tx clock */
+	meson_mmc_clk |= CLK_TX_PHASE_000;
+
+	/* clock settings */
+	meson_mmc_clk |= clk_src;
+	meson_mmc_clk |= clk_div;
+
+	meson_write(mmc, meson_mmc_clk, MESON_SD_EMMC_CLOCK);
+}
+
+static int meson_dm_mmc_set_ios(struct udevice *dev)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	uint32_t meson_mmc_cfg;
+
+	meson_mmc_config_clock(mmc);
+
+	meson_mmc_cfg = meson_read(mmc, MESON_SD_EMMC_CFG);
+
+	meson_mmc_cfg &= ~CFG_BUS_WIDTH_MASK;
+	if (mmc->bus_width == 1)
+		meson_mmc_cfg |= CFG_BUS_WIDTH_1;
+	else if (mmc->bus_width == 4)
+		meson_mmc_cfg |= CFG_BUS_WIDTH_4;
+	else if (mmc->bus_width == 8)
+		meson_mmc_cfg |= CFG_BUS_WIDTH_8;
+	else
+		return -EINVAL;
+
+	/* 512 bytes block length */
+	meson_mmc_cfg &= ~CFG_BL_LEN_MASK;
+	meson_mmc_cfg |= CFG_BL_LEN_512;
+
+	/* Response timeout 256 clk */
+	meson_mmc_cfg &= ~CFG_RESP_TIMEOUT_MASK;
+	meson_mmc_cfg |= CFG_RESP_TIMEOUT_256;
+
+	/* Command-command gap 16 clk */
+	meson_mmc_cfg &= ~CFG_RC_CC_MASK;
+	meson_mmc_cfg |= CFG_RC_CC_16;
+
+	meson_write(mmc, meson_mmc_cfg, MESON_SD_EMMC_CFG);
+
+	return 0;
+}
+
+static void meson_mmc_setup_cmd(struct mmc *mmc, struct mmc_data *data,
+				struct mmc_cmd *cmd)
+{
+	uint32_t meson_mmc_cmd = 0, cfg;
+
+	meson_mmc_cmd |= cmd->cmdidx << CMD_CFG_CMD_INDEX_SHIFT;
+
+	if (cmd->resp_type & MMC_RSP_PRESENT) {
+		if (cmd->resp_type & MMC_RSP_136)
+			meson_mmc_cmd |= CMD_CFG_RESP_128;
+
+		if (cmd->resp_type & MMC_RSP_BUSY)
+			meson_mmc_cmd |= CMD_CFG_R1B;
+
+		if (!(cmd->resp_type & MMC_RSP_CRC))
+			meson_mmc_cmd |= CMD_CFG_RESP_NOCRC;
+	} else {
+		meson_mmc_cmd |= CMD_CFG_NO_RESP;
+	}
+
+	if (data) {
+		cfg = meson_read(mmc, MESON_SD_EMMC_CFG);
+		cfg &= ~CFG_BL_LEN_MASK;
+		cfg |= ilog2(data->blocksize) << CFG_BL_LEN_SHIFT;
+		meson_write(mmc, cfg, MESON_SD_EMMC_CFG);
+
+		if (data->flags == MMC_DATA_WRITE)
+			meson_mmc_cmd |= CMD_CFG_DATA_WR;
+
+		meson_mmc_cmd |= CMD_CFG_DATA_IO | CMD_CFG_BLOCK_MODE |
+				 data->blocks;
+	}
+
+	meson_mmc_cmd |= CMD_CFG_TIMEOUT_4S | CMD_CFG_OWNER |
+			 CMD_CFG_END_OF_CHAIN;
+
+	meson_write(mmc, meson_mmc_cmd, MESON_SD_EMMC_CMD_CFG);
+}
+
+static void meson_mmc_setup_addr(struct mmc *mmc, struct mmc_data *data)
+{
+	struct meson_mmc_platdata *pdata = mmc->priv;
+	unsigned int data_size;
+	uint32_t data_addr = 0;
+
+	if (data) {
+		data_size = data->blocks * data->blocksize;
+
+		if (data->flags == MMC_DATA_READ) {
+			data_addr = (ulong) data->dest;
+			invalidate_dcache_range(data_addr,
+						data_addr + data_size);
+		} else {
+			pdata->w_buf = calloc(data_size, sizeof(char));
+			data_addr = (ulong) pdata->w_buf;
+			memcpy(pdata->w_buf, data->src, data_size);
+			flush_dcache_range(data_addr, data_addr + data_size);
+		}
+	}
+
+	meson_write(mmc, data_addr, MESON_SD_EMMC_CMD_DAT);
+}
+
+static void meson_mmc_read_response(struct mmc *mmc, struct mmc_cmd *cmd)
+{
+	if (cmd->resp_type & MMC_RSP_136) {
+		cmd->response[0] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP3);
+		cmd->response[1] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP2);
+		cmd->response[2] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP1);
+		cmd->response[3] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP);
+	} else {
+		cmd->response[0] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP);
+	}
+}
+
+static int meson_dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+				 struct mmc_data *data)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	struct meson_mmc_platdata *pdata = mmc->priv;
+	uint32_t status;
+	ulong start;
+	int ret = 0;
+
+	/* max block size supported by chip is 512 byte */
+	if (data && data->blocksize > 512)
+		return -EINVAL;
+
+	meson_mmc_setup_cmd(mmc, data, cmd);
+	meson_mmc_setup_addr(mmc, data);
+
+	meson_write(mmc, cmd->cmdarg, MESON_SD_EMMC_CMD_ARG);
+
+	/* use 10s timeout */
+	start = get_timer(0);
+	do {
+		status = meson_read(mmc, MESON_SD_EMMC_STATUS);
+	} while(!(status & STATUS_END_OF_CHAIN) && get_timer(start) < 10000);
+
+	if (!(status & STATUS_END_OF_CHAIN))
+		ret = -ETIMEDOUT;
+	else if (status & STATUS_RESP_TIMEOUT)
+		ret = -ETIMEDOUT;
+	else if (status & STATUS_ERR_MASK)
+		ret = -EIO;
+
+	meson_mmc_read_response(mmc, cmd);
+
+	if (data && data->flags == MMC_DATA_WRITE)
+		free(pdata->w_buf);
+
+	/* reset status bits */
+	meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS);
+
+	return ret;
+}
+
+static const struct dm_mmc_ops meson_dm_mmc_ops = {
+	.send_cmd = meson_dm_mmc_send_cmd,
+	.set_ios = meson_dm_mmc_set_ios,
+};
+
+static int meson_mmc_ofdata_to_platdata(struct udevice *dev)
+{
+	struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
+	fdt_addr_t addr;
+
+	addr = dev_get_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	pdata->regbase = (void *)addr;
+
+	return 0;
+}
+
+static int meson_mmc_probe(struct udevice *dev)
+{
+	struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct mmc *mmc = &pdata->mmc;
+	struct mmc_config *cfg = &pdata->cfg;
+	uint32_t val;
+
+	cfg->voltages = MMC_VDD_33_34 | MMC_VDD_32_33 |
+			MMC_VDD_31_32 | MMC_VDD_165_195;
+	cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT |
+			MMC_MODE_HS_52MHz | MMC_MODE_HS;
+	cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
+	cfg->f_max = 100000000; /* 100 MHz */
+	cfg->b_max = 256; /* max 256 blocks */
+	cfg->name = dev->name;
+
+	mmc->priv = pdata;
+	upriv->mmc = mmc;
+
+	mmc_set_clock(mmc, cfg->f_min);
+
+	/* reset all status bits */
+	meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS);
+
+	/* disable interrupts */
+	meson_write(mmc, 0, MESON_SD_EMMC_IRQ_EN);
+
+	/* enable auto clock mode */
+	val = meson_read(mmc, MESON_SD_EMMC_CFG);
+	val &= ~CFG_SDCLK_ALWAYS_ON;
+	val |= CFG_AUTO_CLK;
+	meson_write(mmc, val, MESON_SD_EMMC_CFG);
+
+	return 0;
+}
+
+int meson_mmc_bind(struct udevice *dev)
+{
+	struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
+
+	return mmc_bind(dev, &pdata->mmc, &pdata->cfg);
+}
+
+static const struct udevice_id meson_mmc_match[] = {
+	{ .compatible = "amlogic,meson-gx-mmc" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(meson_mmc) = {
+	.name = "meson_gx_mmc",
+	.id = UCLASS_MMC,
+	.of_match = meson_mmc_match,
+	.ops = &meson_dm_mmc_ops,
+	.probe = meson_mmc_probe,
+	.bind = meson_mmc_bind,
+	.ofdata_to_platdata = meson_mmc_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct meson_mmc_platdata),
+};
#6 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Am 14.04.2017 um 08:22 schrieb Jaehoon Chung:

Quoted 7 lines · Heiner Kallweit
Quoted 6 lines

From: Carlo Caione <[email protected]>
This driver implements MMC support on Meson GX (S905) based systems. It's based on Carlo Caione's work, changes:
- BLK support added
- general refactoring

Quoted 5 lines
Quoted 3 lines

Applied to u-boot-mmc. Thanks!

Thanks guys for all the work on this!

I have tested it successfully on the Odroid-C2.

But for the Vega S95 Telos I needed to disable the first of three MMC nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks, so that booting failed. I'm not yet sure why, maybe it's a UEFI-side problem in that it is the first MMC device that is absent rather than the last one?

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#7 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Am 15.04.2017 um 17:05 schrieb Andreas Färber:

Quoted 16 lines

Am 14.04.2017 um 08:22 schrieb Jaehoon Chung:

Quoted 7 lines · Heiner Kallweit
Quoted 6 lines

From: Carlo Caione <[email protected]>
This driver implements MMC support on Meson GX (S905) based systems. It's based on Carlo Caione's work, changes:
- BLK support added
- general refactoring

Quoted 5 lines
Quoted 3 lines

Applied to u-boot-mmc. Thanks!

Thanks guys for all the work on this!

Quoted 9 lines

I have tested it successfully on the Odroid-C2.

But for the Vega S95 Telos I needed to disable the first of three MMC nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks, so that booting failed. I'm not yet sure why, maybe it's a UEFI-side problem in that it is the first MMC device that is absent rather than the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

I'm not familiar with distro boot, but as far as I understand Heinrich's patch it just adds mmc0 and mmc1. Therefore distro boot doesn't try to boot from eMMC.

Rgds, Heiner

Quoted 3 lines

Regards,
Andreas

#8 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Quoted 32 lines · Heiner Kallweit

Am 15.04.2017 um 17:05 schrieb Andreas Färber:

Quoted 16 lines

Am 14.04.2017 um 08:22 schrieb Jaehoon Chung:

Quoted 7 lines · Heiner Kallweit
Quoted 6 lines

From: Carlo Caione <[email protected]>
This driver implements MMC support on Meson GX (S905) based systems. It's based on Carlo Caione's work, changes:
- BLK support added
- general refactoring

Quoted 5 lines
Quoted 3 lines

Applied to u-boot-mmc. Thanks!

Thanks guys for all the work on this!

Quoted 9 lines

I have tested it successfully on the Odroid-C2.

But for the Vega S95 Telos I needed to disable the first of three MMC nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks, so that booting failed. I'm not yet sure why, maybe it's a UEFI-side problem in that it is the first MMC device that is absent rather than the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

Quoted 3 lines

I'm not familiar with distro boot, but as far as I understand Heinrich's patch it just adds mmc0 and mmc1. Therefore distro boot doesn't try to boot from eMMC.

If grub comes up, distro boot has successfully found the target binary and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the device names match:

cmd/bootefi.c +0 -0
index 97a0fc9..a98cd95 100644
@@ -364,5 +364,6 @@ void efi_set_bootdev(const char *dev, const char 

*devnr, const char *path)
} else {
snprintf(devname, sizeof(devname), "%s", path);
}
+printf("Setting boot device name to '%s'\n", devname);
ascii2unicode(bootefi_image_path[0].str, devname);
}

lib/efi_loader/efi_disk.c +1 -0
index 1e3dca4..f83fa0e 100644
@@ -207,6 +207,7 @@ static void efi_disk_add_dev(const char *name,
  	if (!desc->lba)
  		return;
 
+printf("Adding disk device '%s'\n", name);
  	diskobj = calloc(1, objlen);
 
  	/* Fill in object data */

Alex

#9 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Quoted 29 lines · Alexander Graf
Quoted 26 lines · Heiner Kallweit

Am 15.04.2017 um 17:05 schrieb Andreas Färber:

Quoted 25 lines

Am 14.04.2017 um 08:22 schrieb Jaehoon Chung:

Quoted 7 lines · Heiner Kallweit
Quoted 6 lines

From: Carlo Caione <[email protected]>
This driver implements MMC support on Meson GX (S905) based systems. It's based on Carlo Caione's work, changes:
- BLK support added
- general refactoring

Quoted 5 lines
Quoted 3 lines

Applied to u-boot-mmc. Thanks!

Thanks guys for all the work on this!

I have tested it successfully on the Odroid-C2.

But for the Vega S95 Telos I needed to disable the first of three MMC nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks, so that booting failed. I'm not yet sure why, maybe it's a UEFI-side problem in that it is the first MMC device that is absent rather than the last one?

Quoted 5 lines
Quoted 5 lines

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

sd_emmc_a - Wireless SDIO Module
sd_emmc_b - SD card
sd_emmc_c - eMMC

Quoted 4 lines
Quoted 4 lines

I'm not familiar with distro boot, but as far as I understand Heinrich's patch it just adds mmc0 and mmc1. Therefore distro boot doesn't try to boot from eMMC.

I will resubmit https://patchwork.ozlabs.org/patch/750859/
odroid-c2: enable MMC as boot target
with 3 MMC targets.

I have tested on my Odroid C2 that the fallthrough to DHCP is still working with 3 defined MMC targets.

Quoted 3 lines

If grub comes up, distro boot has successfully found the target binary and executed it. For some reason, grub can not find its boot origin though.

You could enable
CONFIG_DISPLAY_BOARDINFO=y
CONFIG_CMD_BOOTEFI_HELLO_COMPILE=y

Boardinfo will display the MMC devices detected.

bootefi hello
prints the number of disks detected and handed over to the EFI target.

Quoted 29 lines

Andreas, please add debug prints like the ones below and check that the device names match:

cmd/bootefi.c +1 -0
index 97a0fc9..a98cd95 100644
@@ -364,5 +364,6 @@ void efi_set_bootdev(const char *dev, const char
 *devnr, const char *path)
     } else {
         snprintf(devname, sizeof(devname), "%s", path);
     }
+printf("Setting boot device name to '%s'\n", devname);
     ascii2unicode(bootefi_image_path[0].str, devname);

}

lib/efi_loader/efi_disk.c +1 -0
index 1e3dca4..f83fa0e 100644
@@ -207,6 +207,7 @@ static void efi_disk_add_dev(const char *name,
     if (!desc->lba)
         return;
 
+printf("Adding disk device '%s'\n", name);
     diskobj = calloc(1, objlen);
 
     /* Fill in object data */
Quoted 2 lines

Alex

Wouldn't it make sense to add Alex's patch to mainline?

Best regards

Heinrich Schuchardt

#10 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Quoted 89 lines · Heinrich Schuchardt
Quoted 29 lines · Alexander Graf
Quoted 26 lines · Heiner Kallweit

Am 15.04.2017 um 17:05 schrieb Andreas Färber:

Quoted 25 lines

Am 14.04.2017 um 08:22 schrieb Jaehoon Chung:

Quoted 7 lines · Heiner Kallweit
Quoted 6 lines

From: Carlo Caione <[email protected]>
This driver implements MMC support on Meson GX (S905) based systems. It's based on Carlo Caione's work, changes:
- BLK support added
- general refactoring

Quoted 5 lines
Quoted 3 lines

Applied to u-boot-mmc. Thanks!

Thanks guys for all the work on this!

I have tested it successfully on the Odroid-C2.

But for the Vega S95 Telos I needed to disable the first of three MMC nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks, so that booting failed. I'm not yet sure why, maybe it's a UEFI-side problem in that it is the first MMC device that is absent rather than the last one?

Quoted 5 lines
Quoted 5 lines

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

sd_emmc_a - Wireless SDIO Module
sd_emmc_b - SD card
sd_emmc_c - eMMC

Quoted 4 lines
Quoted 4 lines

I'm not familiar with distro boot, but as far as I understand Heinrich's patch it just adds mmc0 and mmc1. Therefore distro boot doesn't try to boot from eMMC.

I will resubmit https://patchwork.ozlabs.org/patch/750859/
odroid-c2: enable MMC as boot target
with 3 MMC targets.

I have tested on my Odroid C2 that the fallthrough to DHCP is still working with 3 defined MMC targets.

Quoted 3 lines

If grub comes up, distro boot has successfully found the target binary and executed it. For some reason, grub can not find its boot origin though.

You could enable
CONFIG_DISPLAY_BOARDINFO=y
CONFIG_CMD_BOOTEFI_HELLO_COMPILE=y

Boardinfo will display the MMC devices detected.

bootefi hello
prints the number of disks detected and handed over to the EFI target.

Quoted 24 lines

Andreas, please add debug prints like the ones below and check that the device names match:

cmd/bootefi.c +1 -0
index 97a0fc9..a98cd95 100644
@@ -364,5 +364,6 @@ void efi_set_bootdev(const char *dev, const char
 *devnr, const char *path)
     } else {
         snprintf(devname, sizeof(devname), "%s", path);
     }
+printf("Setting boot device name to '%s'\n", devname);
     ascii2unicode(bootefi_image_path[0].str, devname);

}

lib/efi_loader/efi_disk.c +0 -0
index 1e3dca4..f83fa0e 100644
@@ -207,6 +207,7 @@ static void efi_disk_add_dev(const char *name,
     if (!desc->lba)
         return;
 
Quoted 8 lines
Quoted 7 lines
lib/efi_loader/efi_disk.c +1 -0
+printf("Adding disk device '%s'\n", name);
     diskobj = calloc(1, objlen);
 
     /* Fill in object data */

Alex

Wouldn't it make sense to add Alex's patch to mainline?

You usually don't want these debug messages in a proper u-boot build. Maybe as debug prints.

We really need to simply improve on general debuggability of the efi object model though :). I need to sit down and make grub's "lsefi" just work. Ideally that would give us all the hints we need to find out what's going wrong in situations like this, as it has access to all pieces that we need.

Alex

#11 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

In reply to Alexander Graf

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 14 lines · Heiner Kallweit
Quoted 13 lines

Am 15.04.2017 um 17:05 schrieb Andreas Färber:

Quoted 7 lines

But for the Vega S95 Telos I needed to disable the first of three MMC nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks, so that booting failed. I'm not yet sure why, maybe it's a UEFI-side problem in that it is the first MMC device that is absent rather than the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 5 lines

If grub comes up, distro boot has successfully found the target binary and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks
Welcome to GRUB!

error: disk `,msdos2' not found.
Entering rescue mode...
grub rescue>

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#12 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Quoted 51 lines · Andreas Färber

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 14 lines · Heiner Kallweit
Quoted 13 lines

Am 15.04.2017 um 17:05 schrieb Andreas Färber:

Quoted 7 lines

But for the Vega S95 Telos I needed to disable the first of three MMC nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks, so that booting failed. I'm not yet sure why, maybe it's a UEFI-side problem in that it is the first MMC device that is absent rather than the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 5 lines

If grub comes up, distro boot has successfully found the target binary and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks
Welcome to GRUB!

Quoted 7 lines

error: disk `,msdos2' not found.
Entering rescue mode...
grub rescue>

Regards,
Andreas

What is the output of
ls
in grub rescue mode?

Best regards

Heinrich

#13 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Am 15.04.2017 um 22:52 schrieb Heinrich Schuchardt:

Quoted 33 lines · Andreas Färber
Quoted 32 lines

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks
Welcome to GRUB!

error: disk `,msdos2' not found.
Entering rescue mode...
grub rescue>

[...]

Quoted 3 lines

What is the output of
ls
in grub rescue mode?

Entirely empty.

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#14 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

In reply to Andreas Färber
Quoted 39 lines

Am 15.04.2017 um 22:34 schrieb Andreas Färber <[email protected]>:

Quoted 15 lines

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 14 lines · Heiner Kallweit
Quoted 8 lines

Am 15.04.2017 um 17:05 schrieb Andreas Färber:
But for the Vega S95 Telos I needed to disable the first of three MMC nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks, so that booting failed. I'm not yet sure why, maybe it's a UEFI-side problem in that it is the first MMC device that is absent rather than the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 5 lines

If grub comes up, distro boot has successfully found the target binary and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806
Quoted 14 lines

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks

That looks like efi_disk didn't manage to enumerate any devices?

Alex

Quoted 13 lines

Welcome to GRUB!

error: disk `,msdos2' not found.
Entering rescue mode...
grub rescue>

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#15 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Am 15.04.2017 um 23:04 schrieb Alexander Graf:

Quoted 51 lines
Quoted 36 lines

Am 15.04.2017 um 22:34 schrieb Andreas Färber <[email protected]>:

Quoted 15 lines

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 14 lines · Heiner Kallweit
Quoted 8 lines

Am 15.04.2017 um 17:05 schrieb Andreas Färber:
But for the Vega S95 Telos I needed to disable the first of three MMC nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks, so that booting failed. I'm not yet sure why, maybe it's a UEFI-side problem in that it is the first MMC device that is absent rather than the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 5 lines

If grub comes up, distro boot has successfully found the target binary and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806
Quoted 14 lines

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks

Quoted 1 line

That looks like efi_disk didn't manage to enumerate any devices?

Apparently. The last line comes from lib/efi_loader_efi_disk:efi_disk_register(), and CONFIG_BLK=y. As you can see, there is not a single "Scanning disk" line, so I guess we do not iterate over uclass devices properly?

On the Odroid-C2 I get this:

Scanning disk mmc at 72000.blk...
Card did not respond to voltage select!
mmc_init: -95, time 9
Found 1 disks

Therefore my guess that it matters at what point in time - before or after the disk we want - the error accessing an MMC device happens.

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#16 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Am 15.04.2017 um 23:16 schrieb Andreas Färber:

Quoted 61 lines

Am 15.04.2017 um 23:04 schrieb Alexander Graf:

Quoted 51 lines
Quoted 36 lines

Am 15.04.2017 um 22:34 schrieb Andreas Färber <[email protected]>:

Quoted 15 lines

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 14 lines · Heiner Kallweit
Quoted 8 lines

Am 15.04.2017 um 17:05 schrieb Andreas Färber:
But for the Vega S95 Telos I needed to disable the first of three MMC nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks, so that booting failed. I'm not yet sure why, maybe it's a UEFI-side problem in that it is the first MMC device that is absent rather than the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 5 lines

If grub comes up, distro boot has successfully found the target binary and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806
Quoted 14 lines

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks

Quoted 1 line

That looks like efi_disk didn't manage to enumerate any devices?

Apparently. The last line comes from lib/efi_loader_efi_disk:efi_disk_register(), and CONFIG_BLK=y. As you can see, there is not a single "Scanning disk" line, so I guess we do not iterate over uclass devices properly?

On the Odroid-C2 I get this:

Quoted 7 lines

Scanning disk mmc at 72000.blk...
Card did not respond to voltage select!
mmc_init: -95, time 9
Found 1 disks

Therefore my guess that it matters at what point in time - before or after the disk we want - the error accessing an MMC device happens.

For comparison, Vega S95 with first MMC node disabled in DT:

Scanning disk mmc at 72000.blk...
Adding disk device 'mmc at 72000.blk'
** First descriptor is NOT a primary desc on 1:1 ** Scanning disk mmc at 74000.blk...
Adding disk device 'mmc at 74000.blk'
Found 2 disks

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#17 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Quoted 79 lines · Andreas F채rber

Am 15.04.2017 um 23:16 schrieb Andreas F채rber:

Quoted 61 lines

Am 15.04.2017 um 23:04 schrieb Alexander Graf:

Quoted 51 lines
Quoted 36 lines

Am 15.04.2017 um 22:34 schrieb Andreas F채rber <[email protected]>:

Quoted 15 lines

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 14 lines · Heiner Kallweit
Quoted 8 lines

Am 15.04.2017 um 17:05 schrieb Andreas F채rber:
But for the Vega S95 Telos I needed to disable the first of three MMC nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks, so that booting failed. I'm not yet sure why, maybe it's a UEFI-side problem in that it is the first MMC device that is absent rather than the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 5 lines

If grub comes up, distro boot has successfully found the target binary and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806
Quoted 14 lines

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks

Quoted 1 line

That looks like efi_disk didn't manage to enumerate any devices?

Apparently. The last line comes from lib/efi_loader_efi_disk:efi_disk_register(), and CONFIG_BLK=y. As you can see, there is not a single "Scanning disk" line, so I guess we do not iterate over uclass devices properly?

On the Odroid-C2 I get this:

Quoted 7 lines

Scanning disk mmc at 72000.blk...
Card did not respond to voltage select!
mmc_init: -95, time 9
Found 1 disks

Therefore my guess that it matters at what point in time - before or after the disk we want - the error accessing an MMC device happens.

For comparison, Vega S95 with first MMC node disabled in DT:

Scanning disk mmc at 72000.blk...
Adding disk device 'mmc at 72000.blk'
** First descriptor is NOT a primary desc on 1:1 ** Scanning disk mmc at 74000.blk...
Adding disk device 'mmc at 74000.blk'
Found 2 disks

Quoted 3 lines

Regards,
Andreas

By adding sd_mmc_a to the odroid-c2.dts I was able to reproduce the problem on the Odroid C2.

While booting from SD card via booti still worked
bootefi would not find any block device:

=> bootefi hello
## Starting EFI application at 01000000 ...
WARNING: Invalid device tree, expect boot to fail
efi_add_memory_map: 0x7cf53000 0x1 2 yes
uclass_find_device_by_seq: 0 -1
uclass_find_device_by_seq: 0 0
- -1 -1
- -1 -1
- -1 -1
- not found
set_state_simple op missing
blk_get_device: if_type=6, devnum=0: mmc at 70000.blk, 6, 0
mmc_init: -95, time 1807
Found 0 disks
efi_add_memory_map: 0x7cf52000 0x1 6 yes do_bootefi_exec:234 Jumping to 0x7cf53148
EFI: Entry efi_cout_output_string(000000007ff94b38, 000000007cf53280) Hello, world!
EFI: Entry efi_exit(000000007ffa4598, 0, 0, 0000000000000000) ## Application terminated, r = 0

In the debug output you can see that after trying non-existant mmc at 70000.blk no further devices are scanned. mmc at 72000.blk which has the SD card is not enumerated.

Best regards

Heinrich Schuchardt

#18 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Quoted 110 lines · Heinrich Schuchardt
Quoted 79 lines · Andreas F채rber

Am 15.04.2017 um 23:16 schrieb Andreas F채rber:

Quoted 61 lines

Am 15.04.2017 um 23:04 schrieb Alexander Graf:

Quoted 51 lines
Quoted 36 lines

Am 15.04.2017 um 22:34 schrieb Andreas F채rber <[email protected]>:

Quoted 15 lines

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 14 lines · Heiner Kallweit
Quoted 8 lines

Am 15.04.2017 um 17:05 schrieb Andreas F채rber:
But for the Vega S95 Telos I needed to disable the first of three MMC nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks, so that booting failed. I'm not yet sure why, maybe it's a UEFI-side problem in that it is the first MMC device that is absent rather than the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 5 lines

If grub comes up, distro boot has successfully found the target binary and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806
Quoted 14 lines

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks

Quoted 1 line

That looks like efi_disk didn't manage to enumerate any devices?

Apparently. The last line comes from lib/efi_loader_efi_disk:efi_disk_register(), and CONFIG_BLK=y. As you can see, there is not a single "Scanning disk" line, so I guess we do not iterate over uclass devices properly?

On the Odroid-C2 I get this:

Quoted 7 lines

Scanning disk mmc at 72000.blk...
Card did not respond to voltage select!
mmc_init: -95, time 9
Found 1 disks

Therefore my guess that it matters at what point in time - before or after the disk we want - the error accessing an MMC device happens.

For comparison, Vega S95 with first MMC node disabled in DT:

Scanning disk mmc at 72000.blk...
Adding disk device 'mmc at 72000.blk'
** First descriptor is NOT a primary desc on 1:1 ** Scanning disk mmc at 74000.blk...
Adding disk device 'mmc at 74000.blk'
Found 2 disks

Quoted 3 lines

Regards,
Andreas

By adding sd_mmc_a to the odroid-c2.dts I was able to reproduce the problem on the Odroid C2.

While booting from SD card via booti still worked
bootefi would not find any block device:

=> bootefi hello
## Starting EFI application at 01000000 ...
WARNING: Invalid device tree, expect boot to fail
efi_add_memory_map: 0x7cf53000 0x1 2 yes
uclass_find_device_by_seq: 0 -1
uclass_find_device_by_seq: 0 0
- -1 -1
- -1 -1
- -1 -1
- not found
set_state_simple op missing
blk_get_device: if_type=6, devnum=0: mmc at 70000.blk, 6, 0
mmc_init: -95, time 1807
Found 0 disks
efi_add_memory_map: 0x7cf52000 0x1 6 yes do_bootefi_exec:234 Jumping to 0x7cf53148
EFI: Entry efi_cout_output_string(000000007ff94b38, 000000007cf53280) Hello, world!
EFI: Entry efi_exit(000000007ffa4598, 0, 0, 0000000000000000) ## Application terminated, r = 0

Quoted 3 lines

In the debug output you can see that after trying non-existant mmc at 70000.blk no further devices are scanned. mmc at 72000.blk which has the SD card is not enumerated.

To me that looks like something wrong with DM code, as there is no explicit abort condition in efi_disk_register() for the CONFIG_BLK case. Let's CC Simon and ask for help :).

Alex

#19 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Hi Alex,

Quoted 133 lines · Alexander Graf
Quoted 130 lines · Heinrich Schuchardt
Quoted 98 lines · Andreas F채rber

Am 15.04.2017 um 23:16 schrieb Andreas F채rber:

Quoted 78 lines

Am 15.04.2017 um 23:04 schrieb Alexander Graf:

Quoted 66 lines
Quoted 50 lines

Am 15.04.2017 um 22:34 schrieb Andreas F채rber <[email protected]>:

Quoted 22 lines

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 20 lines · Heiner Kallweit
Quoted 13 lines

Am 15.04.2017 um 17:05 schrieb Andreas F채rber:
But for the Vega S95 Telos I needed to disable the first of three MMC
nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks,
so that booting failed. I'm not yet sure why, maybe it's a UEFI-side
problem in that it is the first MMC device that is absent rather than
the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 9 lines

If grub comes up, distro boot has successfully found the target binary
and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the
device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806
Quoted 14 lines

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks

Quoted 1 line

That looks like efi_disk didn't manage to enumerate any devices?

Apparently. The last line comes from lib/efi_loader_efi_disk:efi_disk_register(), and CONFIG_BLK=y. As you can see, there is not a single "Scanning disk" line, so I guess we do not iterate over uclass devices properly?

On the Odroid-C2 I get this:

Quoted 7 lines

Scanning disk mmc at 72000.blk...
Card did not respond to voltage select!
mmc_init: -95, time 9
Found 1 disks

Therefore my guess that it matters at what point in time - before or after the disk we want - the error accessing an MMC device happens.

For comparison, Vega S95 with first MMC node disabled in DT:

Scanning disk mmc at 72000.blk...
Adding disk device 'mmc at 72000.blk'
** First descriptor is NOT a primary desc on 1:1 ** Scanning disk mmc at 74000.blk...
Adding disk device 'mmc at 74000.blk'
Found 2 disks

Quoted 3 lines

Regards,
Andreas

By adding sd_mmc_a to the odroid-c2.dts I was able to reproduce the problem on the Odroid C2.

While booting from SD card via booti still worked
bootefi would not find any block device:

=> bootefi hello
## Starting EFI application at 01000000 ...
WARNING: Invalid device tree, expect boot to fail
efi_add_memory_map: 0x7cf53000 0x1 2 yes
uclass_find_device_by_seq: 0 -1
uclass_find_device_by_seq: 0 0
- -1 -1
- -1 -1
- -1 -1
- not found
set_state_simple op missing
blk_get_device: if_type=6, devnum=0: mmc at 70000.blk, 6, 0
mmc_init: -95, time 1807
Found 0 disks
efi_add_memory_map: 0x7cf52000 0x1 6 yes do_bootefi_exec:234 Jumping to 0x7cf53148
EFI: Entry efi_cout_output_string(000000007ff94b38, 000000007cf53280) Hello, world!
EFI: Entry efi_exit(000000007ffa4598, 0, 0, 0000000000000000) ## Application terminated, r = 0

Quoted 8 lines
Quoted 3 lines

In the debug output you can see that after trying non-existant mmc at 70000.blk no further devices are scanned. mmc at 72000.blk which has the SD card is not enumerated.

To me that looks like something wrong with DM code, as there is no explicit abort condition in efi_disk_register() for the CONFIG_BLK case. Let's CC Simon and ask for help :).

Do you have a board that uses CONFIG_BLK?

Or could we enhance my helloworld test to check the test? I really don't like having to run grub to find bugs :-)

Regards,
Simon

#20 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Quoted 141 lines · Simon Glass

Hi Alex,

Quoted 138 lines · Alexander Graf
Quoted 133 lines · Heinrich Schuchardt
Quoted 98 lines · Andreas F채rber

Am 15.04.2017 um 23:16 schrieb Andreas F채rber:

Quoted 78 lines

Am 15.04.2017 um 23:04 schrieb Alexander Graf:

Quoted 66 lines
Quoted 50 lines

Am 15.04.2017 um 22:34 schrieb Andreas F채rber <[email protected]>:

Quoted 22 lines

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 20 lines · Heiner Kallweit
Quoted 13 lines

Am 15.04.2017 um 17:05 schrieb Andreas F채rber:
But for the Vega S95 Telos I needed to disable the first of three MMC
nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks,
so that booting failed. I'm not yet sure why, maybe it's a UEFI-side
problem in that it is the first MMC device that is absent rather than
the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 9 lines

If grub comes up, distro boot has successfully found the target binary
and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the
device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806
Quoted 14 lines

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks

Quoted 1 line

That looks like efi_disk didn't manage to enumerate any devices?

Apparently. The last line comes from lib/efi_loader_efi_disk:efi_disk_register(), and CONFIG_BLK=y. As you can see, there is not a single "Scanning disk" line, so I guess we do not iterate over uclass devices properly?

On the Odroid-C2 I get this:

Quoted 7 lines

Scanning disk mmc at 72000.blk...
Card did not respond to voltage select!
mmc_init: -95, time 9
Found 1 disks

Therefore my guess that it matters at what point in time - before or after the disk we want - the error accessing an MMC device happens.

For comparison, Vega S95 with first MMC node disabled in DT:

Scanning disk mmc at 72000.blk...
Adding disk device 'mmc at 72000.blk'
** First descriptor is NOT a primary desc on 1:1 ** Scanning disk mmc at 74000.blk...
Adding disk device 'mmc at 74000.blk'
Found 2 disks

Quoted 3 lines

Regards,
Andreas

By adding sd_mmc_a to the odroid-c2.dts I was able to reproduce the problem on the Odroid C2.

While booting from SD card via booti still worked
bootefi would not find any block device:

=> bootefi hello
## Starting EFI application at 01000000 ...
WARNING: Invalid device tree, expect boot to fail
efi_add_memory_map: 0x7cf53000 0x1 2 yes
uclass_find_device_by_seq: 0 -1
uclass_find_device_by_seq: 0 0
- -1 -1
- -1 -1
- -1 -1
- not found
set_state_simple op missing
blk_get_device: if_type=6, devnum=0: mmc at 70000.blk, 6, 0
mmc_init: -95, time 1807
Found 0 disks
efi_add_memory_map: 0x7cf52000 0x1 6 yes do_bootefi_exec:234 Jumping to 0x7cf53148
EFI: Entry efi_cout_output_string(000000007ff94b38, 000000007cf53280) Hello, world!
EFI: Entry efi_exit(000000007ffa4598, 0, 0, 0000000000000000) ## Application terminated, r = 0

In the debug output you can see that after trying non-existant mmc at 70000.blk no further devices are scanned. mmc at 72000.blk which has the SD card is not enumerated.

Quoted 7 lines
Quoted 3 lines

To me that looks like something wrong with DM code, as there is no explicit abort condition in efi_disk_register() for the CONFIG_BLK case. Let's CC Simon and ask for help :).

Do you have a board that uses CONFIG_BLK?

make odroid-c2_defconfig
results in
CONFIG_BLK=y

Quoted 3 lines

Or could we enhance my helloworld test to check the test? I really don't like having to run grub to find bugs :-)

The current debug output is sufficient to demonstrate that the MMC devices are not correctly enumerated for bootefi if the first device cannot be probed.

Regards

Heinrich Schuchardt

#21 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Quoted 116 lines · Heinrich Schuchardt
Quoted 115 lines · Simon Glass

Hi Alex,

Quoted 112 lines · Alexander Graf
Quoted 109 lines · Heinrich Schuchardt
Quoted 98 lines · Andreas F채rber

Am 15.04.2017 um 23:16 schrieb Andreas F채rber:

Quoted 78 lines

Am 15.04.2017 um 23:04 schrieb Alexander Graf:

Quoted 66 lines
Quoted 50 lines

Am 15.04.2017 um 22:34 schrieb Andreas F채rber <[email protected]>:

Quoted 22 lines

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 20 lines · Heiner Kallweit
Quoted 13 lines

Am 15.04.2017 um 17:05 schrieb Andreas F채rber:
But for the Vega S95 Telos I needed to disable the first of three MMC
nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks,
so that booting failed. I'm not yet sure why, maybe it's a UEFI-side
problem in that it is the first MMC device that is absent rather than
the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 9 lines

If grub comes up, distro boot has successfully found the target binary
and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the
device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806
Quoted 14 lines

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks

Quoted 1 line

That looks like efi_disk didn't manage to enumerate any devices?

Apparently. The last line comes from lib/efi_loader_efi_disk:efi_disk_register(), and CONFIG_BLK=y. As you can see, there is not a single "Scanning disk" line, so I guess we do not iterate over uclass devices properly?

On the Odroid-C2 I get this:

Quoted 7 lines

Scanning disk mmc at 72000.blk...
Card did not respond to voltage select!
mmc_init: -95, time 9
Found 1 disks

Therefore my guess that it matters at what point in time - before or after the disk we want - the error accessing an MMC device happens.

For comparison, Vega S95 with first MMC node disabled in DT:

Scanning disk mmc at 72000.blk...
Adding disk device 'mmc at 72000.blk'
** First descriptor is NOT a primary desc on 1:1 ** Scanning disk mmc at 74000.blk...
Adding disk device 'mmc at 74000.blk'
Found 2 disks

Quoted 3 lines

Regards,
Andreas

By adding sd_mmc_a to the odroid-c2.dts I was able to reproduce the problem on the Odroid C2.

While booting from SD card via booti still worked
bootefi would not find any block device:

Quoted 13 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

=> bootefi hello
## Starting EFI application at 01000000 ...
WARNING: Invalid device tree, expect boot to fail
efi_add_memory_map: 0x7cf53000 0x1 2 yes
uclass_find_device_by_seq: 0 -1

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

uclass_find_device_by_seq: 0 0
- -1 -1
- -1 -1
- -1 -1
- not found
set_state_simple op missing
blk_get_device: if_type=6, devnum=0: mmc at 70000.blk, 6, 0
mmc_init: -95, time 1807

This error number is "EOPNOTSUPP". Is "cfg->voltages" correct in meson_gx_mmc.c?

Quoted 40 lines
Quoted 13 lines
Quoted 13 lines
Quoted 11 lines

Found 0 disks
efi_add_memory_map: 0x7cf52000 0x1 6 yes do_bootefi_exec:234 Jumping to 0x7cf53148
EFI: Entry efi_cout_output_string(000000007ff94b38, 000000007cf53280) Hello, world!
EFI: Entry efi_exit(000000007ffa4598, 0, 0, 0000000000000000) ## Application terminated, r = 0

In the debug output you can see that after trying non-existant mmc at 70000.blk no further devices are scanned. mmc at 72000.blk which has the SD card is not enumerated.

Quoted 7 lines
Quoted 3 lines

To me that looks like something wrong with DM code, as there is no explicit abort condition in efi_disk_register() for the CONFIG_BLK case. Let's CC Simon and ask for help :).

Do you have a board that uses CONFIG_BLK?

make odroid-c2_defconfig
results in
CONFIG_BLK=y

Quoted 3 lines

Or could we enhance my helloworld test to check the test? I really don't like having to run grub to find bugs :-)

The current debug output is sufficient to demonstrate that the MMC devices are not correctly enumerated for bootefi if the first device cannot be probed.

Regards

Heinrich Schuchardt

#22 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Hi,

Quoted 131 lines · Jaehoon Chung
Quoted 116 lines · Heinrich Schuchardt
Quoted 115 lines · Simon Glass

Hi Alex,

Quoted 112 lines · Alexander Graf
Quoted 109 lines · Heinrich Schuchardt
Quoted 98 lines · Andreas F채rber

Am 15.04.2017 um 23:16 schrieb Andreas F채rber:

Quoted 78 lines

Am 15.04.2017 um 23:04 schrieb Alexander Graf:

Quoted 66 lines
Quoted 50 lines

Am 15.04.2017 um 22:34 schrieb Andreas F채rber <[email protected]>:

Quoted 22 lines

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 20 lines · Heiner Kallweit
Quoted 13 lines

Am 15.04.2017 um 17:05 schrieb Andreas F채rber:
But for the Vega S95 Telos I needed to disable the first of three MMC
nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks,
so that booting failed. I'm not yet sure why, maybe it's a UEFI-side
problem in that it is the first MMC device that is absent rather than
the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 9 lines

If grub comes up, distro boot has successfully found the target binary
and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the
device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806
Quoted 14 lines

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks

Quoted 1 line

That looks like efi_disk didn't manage to enumerate any devices?

Apparently. The last line comes from lib/efi_loader_efi_disk:efi_disk_register(), and CONFIG_BLK=y. As you can see, there is not a single "Scanning disk" line, so I guess we do not iterate over uclass devices properly?

On the Odroid-C2 I get this:

Quoted 7 lines

Scanning disk mmc at 72000.blk...
Card did not respond to voltage select!
mmc_init: -95, time 9
Found 1 disks

Therefore my guess that it matters at what point in time - before or after the disk we want - the error accessing an MMC device happens.

For comparison, Vega S95 with first MMC node disabled in DT:

Scanning disk mmc at 72000.blk...
Adding disk device 'mmc at 72000.blk'
** First descriptor is NOT a primary desc on 1:1 ** Scanning disk mmc at 74000.blk...
Adding disk device 'mmc at 74000.blk'
Found 2 disks

Quoted 3 lines

Regards,
Andreas

By adding sd_mmc_a to the odroid-c2.dts I was able to reproduce the problem on the Odroid C2.

While booting from SD card via booti still worked
bootefi would not find any block device:

Quoted 13 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

=> bootefi hello
## Starting EFI application at 01000000 ...
WARNING: Invalid device tree, expect boot to fail
efi_add_memory_map: 0x7cf53000 0x1 2 yes
uclass_find_device_by_seq: 0 -1

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

uclass_find_device_by_seq: 0 0
- -1 -1
- -1 -1
- -1 -1
- not found
set_state_simple op missing
blk_get_device: if_type=6, devnum=0: mmc at 70000.blk, 6, 0
mmc_init: -95, time 1807

Quoted 1 line

This error number is "EOPNOTSUPP". Is "cfg->voltages" correct in meson_gx_mmc.c?

Or it could just be that there is no card inserted? See mmc_start_init(). It would be good to update mmc.c to return different errors for the different cases.

Regards,
Simon

#23 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

Quoted 134 lines · Simon Glass

Hi,

Quoted 131 lines · Jaehoon Chung
Quoted 129 lines · Heinrich Schuchardt
Quoted 128 lines · Simon Glass

Hi Alex,

Quoted 125 lines · Alexander Graf
Quoted 122 lines · Heinrich Schuchardt
Quoted 98 lines · Andreas F채rber

Am 15.04.2017 um 23:16 schrieb Andreas F채rber:

Quoted 78 lines

Am 15.04.2017 um 23:04 schrieb Alexander Graf:

Quoted 66 lines
Quoted 50 lines

Am 15.04.2017 um 22:34 schrieb Andreas F채rber <[email protected]>:

Quoted 22 lines

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 20 lines · Heiner Kallweit
Quoted 13 lines

Am 15.04.2017 um 17:05 schrieb Andreas F채rber:
But for the Vega S95 Telos I needed to disable the first of three
MMC
nodes (SDIO) - otherwise U-Boot would happily iterate over them for
distro boot with Heinrich's patch, but GRUB would come up with no
disks,
so that booting failed. I'm not yet sure why, maybe it's a
UEFI-side
problem in that it is the first MMC device that is absent rather
than
the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 9 lines

If grub comes up, distro boot has successfully found the target binary
and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the
device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806
Quoted 14 lines

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks

Quoted 1 line

That looks like efi_disk didn't manage to enumerate any devices?

Apparently. The last line comes from lib/efi_loader_efi_disk:efi_disk_register(), and CONFIG_BLK=y. As you can see, there is not a single "Scanning disk" line, so I guess we do not iterate over uclass devices properly?

On the Odroid-C2 I get this:

Quoted 7 lines

Scanning disk mmc at 72000.blk...
Card did not respond to voltage select!
mmc_init: -95, time 9
Found 1 disks

Therefore my guess that it matters at what point in time - before or after the disk we want - the error accessing an MMC device happens.

For comparison, Vega S95 with first MMC node disabled in DT:

Scanning disk mmc at 72000.blk...
Adding disk device 'mmc at 72000.blk'
** First descriptor is NOT a primary desc on 1:1 ** Scanning disk mmc at 74000.blk...
Adding disk device 'mmc at 74000.blk'
Found 2 disks

Quoted 3 lines

Regards,
Andreas

By adding sd_mmc_a to the odroid-c2.dts I was able to reproduce the problem on the Odroid C2.

While booting from SD card via booti still worked
bootefi would not find any block device:

=> bootefi hello
## Starting EFI application at 01000000 ...
WARNING: Invalid device tree, expect boot to fail
efi_add_memory_map: 0x7cf53000 0x1 2 yes
uclass_find_device_by_seq: 0 -1
uclass_find_device_by_seq: 0 0
- -1 -1
- -1 -1
- -1 -1
- not found
set_state_simple op missing
blk_get_device: if_type=6, devnum=0: mmc at 70000.blk, 6, 0
mmc_init: -95, time 1807

Quoted 5 lines
Quoted 1 line

This error number is "EOPNOTSUPP". Is "cfg->voltages" correct in meson_gx_mmc.c?

Or it could just be that there is no card inserted? See mmc_start_init(). It would be good to update mmc.c to return different errors for the different cases.

Right..Will update.

Quoted 6 lines

Regards,
Simon

#24 lore raw

PATCH v7 2/3 mmc: meson: add MMC driver for Meson GX (S905)

In reply to Simon Glass

Hi Alex,

Quoted 145 lines · Simon Glass

Hi Alex,

Quoted 133 lines · Alexander Graf
Quoted 130 lines · Heinrich Schuchardt
Quoted 98 lines · Andreas F채rber

Am 15.04.2017 um 23:16 schrieb Andreas F채rber:

Quoted 78 lines

Am 15.04.2017 um 23:04 schrieb Alexander Graf:

Quoted 66 lines
Quoted 50 lines

Am 15.04.2017 um 22:34 schrieb Andreas F채rber <[email protected]>:

Quoted 22 lines

Am 15.04.2017 um 20:27 schrieb Alexander Graf:

Quoted 20 lines · Heiner Kallweit
Quoted 13 lines

Am 15.04.2017 um 17:05 schrieb Andreas F채rber:
But for the Vega S95 Telos I needed to disable the first of three MMC
nodes (SDIO) - otherwise U-Boot would happily iterate over them for distro boot with Heinrich's patch, but GRUB would come up with no disks,
so that booting failed. I'm not yet sure why, maybe it's a UEFI-side
problem in that it is the first MMC device that is absent rather than
the last one?

I don't own this device so I can just provide a guess. Based on DT the device ordering most likely is:
mmc0: SDIO
mmc1: SD
mmc2: eMMC

[...]

Quoted 9 lines

If grub comes up, distro boot has successfully found the target binary
and executed it. For some reason, grub can not find its boot origin though.

Andreas, please add debug prints like the ones below and check that the
device names match:

U-Boot 2017.05-rc1-00318-g082535f-dirty (Apr 15 2017 - 22:29:17 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806
Quoted 14 lines

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 43 ms (460.9 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 13 ms (9.5 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1807
Found 0 disks

Quoted 1 line

That looks like efi_disk didn't manage to enumerate any devices?

Apparently. The last line comes from lib/efi_loader_efi_disk:efi_disk_register(), and CONFIG_BLK=y. As you can see, there is not a single "Scanning disk" line, so I guess we do not iterate over uclass devices properly?

On the Odroid-C2 I get this:

Quoted 7 lines

Scanning disk mmc at 72000.blk...
Card did not respond to voltage select!
mmc_init: -95, time 9
Found 1 disks

Therefore my guess that it matters at what point in time - before or after the disk we want - the error accessing an MMC device happens.

For comparison, Vega S95 with first MMC node disabled in DT:

Scanning disk mmc at 72000.blk...
Adding disk device 'mmc at 72000.blk'
** First descriptor is NOT a primary desc on 1:1 ** Scanning disk mmc at 74000.blk...
Adding disk device 'mmc at 74000.blk'
Found 2 disks

Quoted 3 lines

Regards,
Andreas

By adding sd_mmc_a to the odroid-c2.dts I was able to reproduce the problem on the Odroid C2.

While booting from SD card via booti still worked
bootefi would not find any block device:

=> bootefi hello
## Starting EFI application at 01000000 ...
WARNING: Invalid device tree, expect boot to fail
efi_add_memory_map: 0x7cf53000 0x1 2 yes
uclass_find_device_by_seq: 0 -1
uclass_find_device_by_seq: 0 0
- -1 -1
- -1 -1
- -1 -1
- not found
set_state_simple op missing
blk_get_device: if_type=6, devnum=0: mmc at 70000.blk, 6, 0
mmc_init: -95, time 1807
Found 0 disks
efi_add_memory_map: 0x7cf52000 0x1 6 yes do_bootefi_exec:234 Jumping to 0x7cf53148
EFI: Entry efi_cout_output_string(000000007ff94b38, 000000007cf53280) Hello, world!
EFI: Entry efi_exit(000000007ffa4598, 0, 0, 0000000000000000) ## Application terminated, r = 0

Quoted 8 lines
Quoted 3 lines

In the debug output you can see that after trying non-existant mmc at 70000.blk no further devices are scanned. mmc at 72000.blk which has the SD card is not enumerated.

To me that looks like something wrong with DM code, as there is no explicit abort condition in efi_disk_register() for the CONFIG_BLK case. Let's CC Simon and ask for help :).

Quoted 6 lines

Do you have a board that uses CONFIG_BLK?

Or could we enhance my helloworld test to check the test? I really don't like having to run grub to find bugs :-)

Any thoughts on this one?

Regards,
Simon

#25 lore raw

PATCH 1/1 core/uclass: uclass_get_device_tail: always set devp

In reply to Andreas Färber

Set devp even if probing fails.

Without the patch the following problem occurs:
If the first block device is not probed successfully no block device is passed by bootefi to the EFI executable.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
	status = "okay";
}

This device does not exist on the board and cannot be initialized.

---
 drivers/core/uclass.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/core/uclass.c +3 -2
index 04fb45b..b647384 100644
@@ -349,12 +349,13 @@ int uclass_get_device_tail(struct udevice *dev, int ret,
 		return ret;
 
 	assert(dev);
+
+	*devp = dev;
+
 	ret = device_probe(dev);
 	if (ret)
 		return ret;
 
-	*devp = dev;
-
 	return 0;
 }
 
Signature · 1 line
2.1.4
#26 lore raw

PATCH 1/1 core/uclass: uclass_get_device_tail: always set devp

Hi,

Quoted 6 lines · Heinrich Schuchardt

Set devp even if probing fails.

Without the patch the following problem occurs:
If the first block device is not probed successfully no block device is passed by bootefi to the EFI executable.

Quoted 8 lines

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

Thanks for finding this. Which function is calling this? Can you please explain the call sequence to hit this problem? I am worried that something else is wrong.

Quoted 28 lines
---
 drivers/core/uclass.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/core/uclass.c +3 -3
index 04fb45b..b647384 100644
@@ -349,12 +349,13 @@ int uclass_get_device_tail(struct udevice *dev, int ret,
                return ret;
 
        assert(dev);
+
+       *devp = dev;
+
        ret = device_probe(dev);
        if (ret)
                return ret;
 
-       *devp = dev;
-
        return 0;
 }
 
--
Quoted 2 lines

2.1.4

Regards,
Simon

#27 lore raw

PATCH 1/1 core/uclass: uclass_get_device_tail: always set devp

Hi Simon,

Am 19.04.2017 um 02:12 schrieb Simon Glass:

Quoted 16 lines · Heinrich Schuchardt
Quoted 6 lines

Set devp even if probing fails.

Without the patch the following problem occurs:
If the first block device is not probed successfully no block device is passed by bootefi to the EFI executable.

Quoted 8 lines

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

Quoted 3 lines

Thanks for finding this. Which function is calling this? Can you please explain the call sequence to hit this problem? I am worried that something else is wrong.

It is lib/efi_loader/efi_disk.c:efi_disk_register() that is calling uclass_first_device() and uclass_next_device(). Based on the output we had concluded that uclass_first_device() fails already - therefore Alex CC'ed you.

Unfortunately I find the function interactions inside uclass.c rather complex and unintuitive, so I am truely amazed at Heinrich's findings. (Passing the ret code from one function to the next just to return?!)

Based on his patch we can assume that uclass_find_first_device() set dev to a non-NULL value, otherwise we wouldn't end up in uclass_get_device_tail().

So if you're saying this patch is wrong, then that would leave device_probe(). The actual meson_mmc_probe() function you had given a late Reviewed-by, and it always returns 0.

Jaehoon had asked about cfg->voltages in meson_mmc_probe(), but I don't see how that would lead to probe failure here? Whether the values are correct I have no idea.

The error message "mmc_init: -95, time 1807", which appears to be a result of this iteration/probe process, comes from drivers/mmc/mmc.c:mmc_init(), which is called from mmc-uclass.c:mmc_blk_probe(). mmc_init() calls mmc_start_init(), which returns this -EOPNOTSUPP if sd_send_op_cond return -ETIMEDOUT and mmc_send_op_cond() failed. However, our output does not show "Card did not respond to voltage select!", which it should in that case. So the error must be coming from elsewhere. sd_send_op_cond() may return -EOPNOTSUPP through mmc_start_init(), and so does mmc_complete_op_cond() through mmc_complete_init(). I would expect either to fail, as in my case it's an SDIO, and in Heinrich's case it's not connected to anything. So I don't think MMC is at fault here.

https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi

See sd_mmc_a, which uses an mmc-pwrseq that depends on a pwm-clock, neither of which have any support in U-Boot, nor is it actually needed for booting.

In any case, failure to probe one device should not break the iteration of other devices. I.e., if a device fails to probe then instead of returning from uclass_{first,next}_device() we should look at the next device until we find one that's okay or have reached the end of the list. How to best implement that in uclass.c I'm less sure of.

If I am right you could test this on any board with multiple, e.g., blk devices where a first or non-last device returns an error code from its probe, i.e. try changing return 0 in some probe function based on a static variable not yet being initialized or something. Probably you could even write some tiny sandbox based test, without actual hardware.

IIUC this patch changes behavior from iterating over no devices to iterating over all devices including ones not probed successfully? And what you intended was to instead iterate over only the probed devices?

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#28 lore raw

PATCH 1/1 core/uclass: uclass_get_device_tail: always set devp

Hi,

Quoted 75 lines · Andreas Färber

Hi Simon,

Am 19.04.2017 um 02:12 schrieb Simon Glass:

Quoted 16 lines · Heinrich Schuchardt
Quoted 6 lines

Set devp even if probing fails.

Without the patch the following problem occurs:
If the first block device is not probed successfully no block device is passed by bootefi to the EFI executable.

Quoted 8 lines

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

Quoted 3 lines

Thanks for finding this. Which function is calling this? Can you please explain the call sequence to hit this problem? I am worried that something else is wrong.

It is lib/efi_loader/efi_disk.c:efi_disk_register() that is calling uclass_first_device() and uclass_next_device(). Based on the output we had concluded that uclass_first_device() fails already - therefore Alex CC'ed you.

Unfortunately I find the function interactions inside uclass.c rather complex and unintuitive, so I am truely amazed at Heinrich's findings. (Passing the ret code from one function to the next just to return?!)

Based on his patch we can assume that uclass_find_first_device() set dev to a non-NULL value, otherwise we wouldn't end up in uclass_get_device_tail().

So if you're saying this patch is wrong, then that would leave device_probe(). The actual meson_mmc_probe() function you had given a late Reviewed-by, and it always returns 0.

Jaehoon had asked about cfg->voltages in meson_mmc_probe(), but I don't see how that would lead to probe failure here? Whether the values are correct I have no idea.

The error message "mmc_init: -95, time 1807", which appears to be a result of this iteration/probe process, comes from drivers/mmc/mmc.c:mmc_init(), which is called from mmc-uclass.c:mmc_blk_probe(). mmc_init() calls mmc_start_init(), which returns this -EOPNOTSUPP if sd_send_op_cond return -ETIMEDOUT and mmc_send_op_cond() failed. However, our output does not show "Card did not respond to voltage select!", which it should in that case. So the error must be coming from elsewhere. sd_send_op_cond() may return -EOPNOTSUPP through mmc_start_init(), and so does mmc_complete_op_cond() through mmc_complete_init(). I would expect either to fail, as in my case it's an SDIO, and in Heinrich's case it's not connected to anything. So I don't think MMC is at fault here.

https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi

See sd_mmc_a, which uses an mmc-pwrseq that depends on a pwm-clock, neither of which have any support in U-Boot, nor is it actually needed for booting.

In any case, failure to probe one device should not break the iteration of other devices. I.e., if a device fails to probe then instead of returning from uclass_{first,next}_device() we should look at the next device until we find one that's okay or have reached the end of the list. How to best implement that in uclass.c I'm less sure of.

If I am right you could test this on any board with multiple, e.g., blk devices where a first or non-last device returns an error code from its probe, i.e. try changing return 0 in some probe function based on a static variable not yet being initialized or something. Probably you could even write some tiny sandbox based test, without actual hardware.

Quoted 3 lines

IIUC this patch changes behavior from iterating over no devices to iterating over all devices including ones not probed successfully? And what you intended was to instead iterate over only the probed devices?

I think this is a genuine bug, but exactly where is less obvious.

The uclass function don't return a device if they get an error. So at present you need to iterate through the uclass if the intention is to continue after error. That would be uclass_foreach_dev(). But before using the device, device_probe() needs to be called since the iteration does not probe it automatically. That is why people normally use uclass_first/next_device(), since it probes as it goes.

However in this case I think it is reasonable to change uclass_first/next_device() to always return the device, even on error. That can best be done by changing those functions rather than uclass_get_device_tail(), which is shared by many functions. We should not change uclass_get_device_tail() since what is does is correct for all other uses (I think).

In that case, the function comments for the first/next functions should be updated to indicate the new behaviour, and a test created, perhaps in test/dm/core.c.

You were asking about uclass_get_device_tail(). This is common code and is put into a function to ensure consistent behaviour across all functions that return an error code and a device. Consistency is very important with driver model since things can get version confusing when something odd happens in the bowels of the system, as this bug has shown.

Regards,
Simon

#29 lore raw

PATCH 1/1 core/uclass: uclass_get_device_tail: always set devp

Quoted 109 lines · Simon Glass

Hi,

Quoted 75 lines · Andreas Färber

Hi Simon,

Am 19.04.2017 um 02:12 schrieb Simon Glass:

Quoted 16 lines · Heinrich Schuchardt
Quoted 6 lines

Set devp even if probing fails.

Without the patch the following problem occurs:
If the first block device is not probed successfully no block device is passed by bootefi to the EFI executable.

Quoted 8 lines

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

Quoted 3 lines

Thanks for finding this. Which function is calling this? Can you please explain the call sequence to hit this problem? I am worried that something else is wrong.

It is lib/efi_loader/efi_disk.c:efi_disk_register() that is calling uclass_first_device() and uclass_next_device(). Based on the output we had concluded that uclass_first_device() fails already - therefore Alex CC'ed you.

Unfortunately I find the function interactions inside uclass.c rather complex and unintuitive, so I am truely amazed at Heinrich's findings. (Passing the ret code from one function to the next just to return?!)

Based on his patch we can assume that uclass_find_first_device() set dev to a non-NULL value, otherwise we wouldn't end up in uclass_get_device_tail().

So if you're saying this patch is wrong, then that would leave device_probe(). The actual meson_mmc_probe() function you had given a late Reviewed-by, and it always returns 0.

Jaehoon had asked about cfg->voltages in meson_mmc_probe(), but I don't see how that would lead to probe failure here? Whether the values are correct I have no idea.

The error message "mmc_init: -95, time 1807", which appears to be a result of this iteration/probe process, comes from drivers/mmc/mmc.c:mmc_init(), which is called from mmc-uclass.c:mmc_blk_probe(). mmc_init() calls mmc_start_init(), which returns this -EOPNOTSUPP if sd_send_op_cond return -ETIMEDOUT and mmc_send_op_cond() failed. However, our output does not show "Card did not respond to voltage select!", which it should in that case. So the error must be coming from elsewhere. sd_send_op_cond() may return -EOPNOTSUPP through mmc_start_init(), and so does mmc_complete_op_cond() through mmc_complete_init(). I would expect either to fail, as in my case it's an SDIO, and in Heinrich's case it's not connected to anything. So I don't think MMC is at fault here.

https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi

See sd_mmc_a, which uses an mmc-pwrseq that depends on a pwm-clock, neither of which have any support in U-Boot, nor is it actually needed for booting.

In any case, failure to probe one device should not break the iteration of other devices. I.e., if a device fails to probe then instead of returning from uclass_{first,next}_device() we should look at the next device until we find one that's okay or have reached the end of the list. How to best implement that in uclass.c I'm less sure of.

If I am right you could test this on any board with multiple, e.g., blk devices where a first or non-last device returns an error code from its probe, i.e. try changing return 0 in some probe function based on a static variable not yet being initialized or something. Probably you could even write some tiny sandbox based test, without actual hardware.

Quoted 3 lines

IIUC this patch changes behavior from iterating over no devices to iterating over all devices including ones not probed successfully? And what you intended was to instead iterate over only the probed devices?

I think this is a genuine bug, but exactly where is less obvious.

The uclass function don't return a device if they get an error. So at present you need to iterate through the uclass if the intention is to continue after error. That would be uclass_foreach_dev(). But before using the device, device_probe() needs to be called since the iteration does not probe it automatically. That is why people normally use uclass_first/next_device(), since it probes as it goes.

However in this case I think it is reasonable to change uclass_first/next_device() to always return the device, even on error. That can best be done by changing those functions rather than uclass_get_device_tail(), which is shared by many functions. We should not change uclass_get_device_tail() since what is does is correct for all other uses (I think).

In that case, the function comments for the first/next functions should be updated to indicate the new behaviour, and a test created, perhaps in test/dm/core.c.

You were asking about uclass_get_device_tail(). This is common code and is put into a function to ensure consistent behaviour across all functions that return an error code and a device. Consistency is very important with driver model since things can get version confusing when something odd happens in the bowels of the system, as this bug has shown.

Quoted 3 lines

Regards,
Simon

Thank you Simon for reviewing. I will try to rework the patch.

For reference I append the debug output with and without the current patch. This should make the call sequence clear.

In uclass_first_device: id 12
12 refers to UCLASS_BLK.

Best regards

Heinrich Schuchardt

Without [PATCH 1/1] core/uclass: uclass_get_device_tail: always set devp

=> bootefi hello
## Starting EFI application at 01000000 ...
WARNING: Invalid device tree, expect boot to fail
efi_add_memory_map: 0x7cf50000 0x1 2 yes
efi_disk_register
uclass_first_device: id 12
uclass_find_first_device: id 12
uclass_get_device_tail: ret 0
uclass_resolve_seq:
uclass_find_device_by_seq: uclass_id 0, seq_or_req_seq -1, find_req_seq 0
uclass_find_device_by_seq: uclass_id 0, seq_or_req_seq 0, find_req_seq 0 mmc at 70000.blk - -1 -1
mmc at 72000.blk - -1 -1
mmc at 74000.blk - -1 -1
- not found
uclass_get_device: id 41, index 0
uclass_get_device_tail: ret 0
set_state_simple op missing
find_mmc_device: dev_num 0
blk_get_device: if_type=6, devnum=0: mmc at 70000.blk, 6, 0 mmc_blk_probe
mmc_init: -95, time 1807
Found 0 disks
uclass_first_device: id 18
uclass_find_first_device: id 18
uclass_get_device_tail: ret 0
efi_add_memory_map: 0x7cf4f000 0x1 6 yes
do_bootefi_exec:234 Jumping to 0x7cf50148
EFI: Entry efi_cout_output_string(000000007ff93ac0, 000000007cf50274) Hello, world!
EFI: Entry efi_exit(000000007ffa47d0, 0, 0, 0000000000000000) ## Application terminated, r = 0
=>

With [PATCH 1/1] core/uclass: uclass_get_device_tail: always set devp

=> bootefi hello
## Starting EFI application at 01000000 ...
WARNING: Invalid device tree, expect boot to fail
efi_add_memory_map: 0x7cf50000 0x1 2 yes
efi_disk_register
uclass_first_device: id 12
uclass_find_first_device: id 12
uclass_get_device_tail: ret 0
uclass_resolve_seq:
uclass_find_device_by_seq: uclass_id 0, seq_or_req_seq -1, find_req_seq 0
uclass_find_device_by_seq: uclass_id 0, seq_or_req_seq 0, find_req_seq 0 mmc at 70000.blk - -1 -1
mmc at 72000.blk - -1 0
- found
uclass_find_device_by_seq: uclass_id 0, seq_or_req_seq 1, find_req_seq 0 mmc at 70000.blk - -1 -1
mmc at 72000.blk - -1 0
mmc at 74000.blk - -1 -1
- not found
uclass_get_device: id 41, index 0
uclass_get_device_tail: ret 0
set_state_simple op missing
find_mmc_device: dev_num 0
blk_get_device: if_type=6, devnum=0: mmc at 70000.blk, 6, 0 mmc_blk_probe
mmc_init: -95, time 1806
Scanning disk mmc at 70000.blk...
uclass_next_device:
uclass_find_next_device:
uclass_get_device_tail: ret 0
Scanning disk mmc at 72000.blk...
Adding disk device 'mmc at 72000.blk'
uclass_next_device:
uclass_find_next_device:
uclass_get_device_tail: ret 0
uclass_resolve_seq:
uclass_find_device_by_seq: uclass_id 0, seq_or_req_seq -1, find_req_seq 0
uclass_find_device_by_seq: uclass_id 0, seq_or_req_seq 0, find_req_seq 0 mmc at 70000.blk - -1 -1
mmc at 72000.blk - -1 0
- found
uclass_find_device_by_seq: uclass_id 0, seq_or_req_seq 1, find_req_seq 0 mmc at 70000.blk - -1 -1
mmc at 72000.blk - -1 0
mmc at 74000.blk - -1 -1
- not found
uclass_get_device: id 41, index 0
uclass_get_device_tail: ret 0
set_state_simple op missing
find_mmc_device: dev_num 2
blk_get_device: if_type=6, devnum=2: mmc at 70000.blk, 6, 0
blk_get_device: if_type=6, devnum=2: mmc at 72000.blk, 6, 1
blk_get_device: if_type=6, devnum=2: mmc at 74000.blk, 6, 2 mmc_blk_probe
Card did not respond to voltage select!
mmc_init: -95, time 10
Scanning disk mmc at 74000.blk...
uclass_next_device:
uclass_find_next_device:
Found 3 disks
efi_add_memory_map: 0x7cf4f000 0x1 6 yes
do_bootefi_exec:234 Jumping to 0x7cf50148
EFI: Entry efi_cout_output_string(000000007ff93ad0, 000000007cf50274) Hello, world!
EFI: Entry efi_exit(000000007ffa47e0, 0, 0, 0000000000000000) ## Application terminated, r = 0
=>

#30 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

In reply to Simon Glass

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
	status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)
drivers/core/uclass.c +33 -11
index 04fb45b..cff3a3f 100644
@@ -420,16 +420,30 @@ int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent,
 }
 #endif
 
+/**
+ * uclass_first_device() - Finds first device of an uclass that can be probed
+ * @id: uclass id
+ * @devp: device found or NULL
+ * @return always 0
+ *
+ * For iterating over all devices of an uclass use
+ * for(uclass_first_device(id, &dev); dev; uclass_next_device(&dev)).
+ */
 int uclass_first_device(enum uclass_id id, struct udevice **devp)
 {
 	struct udevice *dev;
-	int ret;
 
 	*devp = NULL;
-	ret = uclass_find_first_device(id, &dev);
-	if (!dev)
-		return 0;
-	return uclass_get_device_tail(dev, ret, devp);
+	for (uclass_find_first_device(id, &dev); dev;
+	     uclass_find_next_device(&dev)) {
+
+		uclass_get_device_tail(dev, 0, devp);
+		if (*devp)
+			break;
+	}
+	debug("%s(%d): %s\n", __func__, id, dev ? dev->name : "(EOL)");
+
+	return 0;
 }
 
 int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
@@ -445,16 +459,24 @@ int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
 	return 0;
 }
 
+/**
+ * uclass_next_device() - Find next device of an uclass that can be probed
+ * @devp: device found or NULL
+ * @return always 0
+ */
 int uclass_next_device(struct udevice **devp)
 {
 	struct udevice *dev = *devp;
-	int ret;
 
-	*devp = NULL;
-	ret = uclass_find_next_device(&dev);
-	if (!dev)
-		return 0;
-	return uclass_get_device_tail(dev, ret, devp);
+	for (*devp = NULL; !*devp; ) {
+		uclass_find_next_device(&dev);
+		if (!dev)
+			break;
+		uclass_get_device_tail(dev, 0, devp);
+	}
+	debug("%s: %s\n", __func__, dev ? dev->name : "(EOL)");
+
+	return 0;
 }
 
 int uclass_bind_device(struct udevice *dev)
Signature · 1 line
2.1.4
#31 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Hi Heinrich,

Quoted 9 lines · Heinrich Schuchardt

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

Quoted 8 lines
&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

I would like to avoid changing the API that much. Can you please change it to stop calling the tail function and always set the device, like you did in v1?

Also don't forget to add a test for this bahaviour. You may need to have sandbox device that returns an error when probing. Perhaps add another compatible string to denx,u-boot-fdt-test?

Quoted 15 lines

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

Quoted 4 lines
---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)

Regards,
Simon

#32 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Hi Simon,

Am 19.04.2017 um 16:28 schrieb Simon Glass:

Quoted 15 lines · Heinrich Schuchardt
Quoted 14 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

Quoted 7 lines
Quoted 3 lines

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

I would like to avoid changing the API that much. Can you please change it to stop calling the tail function and always set the device, like you did in v1?

I fear you're missing the key point I made in my lengthy explanation:

Our caller (EFI) wants to iterate over the available devices. SDIO is not available. If we return a non-NULL device it will try to scan the disk. Therefore I think v2 is more correct (not yet tested).

So really the question is what your desired semantics of this function are and how callers here and elsewhere are handling it. If we want to return non-probed devices to the caller, as you now suggest, then we would need to audit and amend all callers of the API with some "if !is_probed() then continue" check. If we simply skip them internally, as done here IIUC, we require no changes on the caller side, thus much less invasive.

Maybe we need a new API uclass_{first,next}_available_device() to make this clear? The change would then only affect callers of the new API, and EFI and possibly others would again need to be audited and updated.

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#33 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Hi Andreas,

Quoted 22 lines · Andreas Färber

Hi Simon,

Am 19.04.2017 um 16:28 schrieb Simon Glass:

Quoted 19 lines · Heinrich Schuchardt
Quoted 17 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Quoted 5 lines
Quoted 3 lines

I would like to avoid changing the API that much. Can you please change it to stop calling the tail function and always set the device, like you did in v1?

I fear you're missing the key point I made in my lengthy explanation:

That's not entirely impossible.

Quoted 5 lines

Our caller (EFI) wants to iterate over the available devices. SDIO is not available. If we return a non-NULL device it will try to scan the disk. Therefore I think v2 is more correct (not yet tested).

Quoted 7 lines

So really the question is what your desired semantics of this function are and how callers here and elsewhere are handling it. If we want to return non-probed devices to the caller, as you now suggest, then we would need to audit and amend all callers of the API with some "if !is_probed() then continue" check. If we simply skip them internally, as done here IIUC, we require no changes on the caller side, thus much less invasive.

Well the value of 'ret' gives you that information if you want it. But yes it is a change and on second thoughts I'm not entirely comfortable with it.

Quoted 4 lines

Maybe we need a new API uclass_{first,next}_available_device() to make this clear? The change would then only affect callers of the new API, and EFI and possibly others would again need to be audited and updated.

Actually how about we go back to my foreach idea, and have a manual probe. So I mean let's just change the EFI code.

See for example print_cpu_list() for how this is done.

Regards,
Simon

#34 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Hi Andreas,

Quoted 46 lines · Simon Glass

Hi Andreas,

Quoted 22 lines · Andreas Färber

Hi Simon,

Am 19.04.2017 um 16:28 schrieb Simon Glass:

Quoted 19 lines · Heinrich Schuchardt
Quoted 17 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Quoted 5 lines
Quoted 3 lines

I would like to avoid changing the API that much. Can you please change it to stop calling the tail function and always set the device, like you did in v1?

I fear you're missing the key point I made in my lengthy explanation:

That's not entirely impossible.

Quoted 5 lines

Our caller (EFI) wants to iterate over the available devices. SDIO is not available. If we return a non-NULL device it will try to scan the disk. Therefore I think v2 is more correct (not yet tested).

Quoted 7 lines

So really the question is what your desired semantics of this function are and how callers here and elsewhere are handling it. If we want to return non-probed devices to the caller, as you now suggest, then we would need to audit and amend all callers of the API with some "if !is_probed() then continue" check. If we simply skip them internally, as done here IIUC, we require no changes on the caller side, thus much less invasive.

Quoted 8 lines

Well the value of 'ret' gives you that information if you want it. But yes it is a change and on second thoughts I'm not entirely comfortable with it.

Quoted 4 lines

Maybe we need a new API uclass_{first,next}_available_device() to make this clear? The change would then only affect callers of the new API, and EFI and possibly others would again need to be audited and updated.

If you think this is generally useful then you could add this. I think it would be something like:

for (ret = uclass_first_avail_device(UCLASS_..., &dev; dev; ret =

uclass_next_avail_device(&dev)) {
    if (!ret) {
       // do something

}
}

Does that sounds right?

Quoted 5 lines

Actually how about we go back to my foreach idea, and have a manual probe. So I mean let's just change the EFI code.

See for example print_cpu_list() for how this is done.

Regards,
Simon

#35 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Am 19.04.2017 um 17:52 schrieb Simon Glass:

Quoted 61 lines

Hi Andreas,

Quoted 46 lines · Simon Glass

Hi Andreas,

Quoted 22 lines · Andreas Färber

Hi Simon,

Am 19.04.2017 um 16:28 schrieb Simon Glass:

Quoted 19 lines · Heinrich Schuchardt
Quoted 17 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Quoted 5 lines
Quoted 3 lines

I would like to avoid changing the API that much. Can you please change it to stop calling the tail function and always set the device, like you did in v1?

I fear you're missing the key point I made in my lengthy explanation:

That's not entirely impossible.

Quoted 5 lines

Our caller (EFI) wants to iterate over the available devices. SDIO is not available. If we return a non-NULL device it will try to scan the disk. Therefore I think v2 is more correct (not yet tested).

Quoted 7 lines

So really the question is what your desired semantics of this function are and how callers here and elsewhere are handling it. If we want to return non-probed devices to the caller, as you now suggest, then we would need to audit and amend all callers of the API with some "if !is_probed() then continue" check. If we simply skip them internally, as done here IIUC, we require no changes on the caller side, thus much less invasive.

Quoted 8 lines

Well the value of 'ret' gives you that information if you want it. But yes it is a change and on second thoughts I'm not entirely comfortable with it.

Quoted 4 lines

Maybe we need a new API uclass_{first,next}_available_device() to make this clear? The change would then only affect callers of the new API, and EFI and possibly others would again need to be audited and updated.

If you think this is generally useful then you could add this. I think it would be something like:

Quoted 8 lines

for (ret = uclass_first_avail_device(UCLASS_..., &dev; dev; ret =

uclass_next_avail_device(&dev)) {
    if (!ret) {
       // do something

}
}

Does that sounds right?

No. I think that should be the semantics of uclass_first_device(), i.e. Heinrich's v1, possibly moved out of _tail() as you requested.

The idea behind a separate ..._available_device() implementation was to not have to do that ret check and to simply replace the function name to change the semantics, i.e. Heinrich's v2 implementation, but not inside uclass_{first,next}_device() but in copies with different name.

What use case is there for an incomplete enumeration as done by uclass_first_device() today? In order to continue enumeration devp needs to be set IIUC.

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#36 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Hi Andreas,

Quoted 71 lines · Andreas Färber

Am 19.04.2017 um 17:52 schrieb Simon Glass:

Quoted 61 lines

Hi Andreas,

Quoted 46 lines · Simon Glass

Hi Andreas,

Quoted 22 lines · Andreas Färber

Hi Simon,

Am 19.04.2017 um 16:28 schrieb Simon Glass:

Quoted 19 lines · Heinrich Schuchardt
Quoted 17 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Quoted 5 lines
Quoted 3 lines

I would like to avoid changing the API that much. Can you please change it to stop calling the tail function and always set the device, like you did in v1?

I fear you're missing the key point I made in my lengthy explanation:

That's not entirely impossible.

Quoted 5 lines

Our caller (EFI) wants to iterate over the available devices. SDIO is not available. If we return a non-NULL device it will try to scan the disk. Therefore I think v2 is more correct (not yet tested).

Quoted 7 lines

So really the question is what your desired semantics of this function are and how callers here and elsewhere are handling it. If we want to return non-probed devices to the caller, as you now suggest, then we would need to audit and amend all callers of the API with some "if !is_probed() then continue" check. If we simply skip them internally, as done here IIUC, we require no changes on the caller side, thus much less invasive.

Quoted 8 lines

Well the value of 'ret' gives you that information if you want it. But yes it is a change and on second thoughts I'm not entirely comfortable with it.

Quoted 4 lines

Maybe we need a new API uclass_{first,next}_available_device() to make this clear? The change would then only affect callers of the new API, and EFI and possibly others would again need to be audited and updated.

If you think this is generally useful then you could add this. I think it would be something like:

Quoted 8 lines

for (ret = uclass_first_avail_device(UCLASS_..., &dev; dev; ret =

uclass_next_avail_device(&dev)) {
    if (!ret) {
       // do something

}
}

Does that sounds right?

Quoted 7 lines

No. I think that should be the semantics of uclass_first_device(), i.e. Heinrich's v1, possibly moved out of _tail() as you requested.

The idea behind a separate ..._available_device() implementation was to not have to do that ret check and to simply replace the function name to change the semantics, i.e. Heinrich's v2 implementation, but not inside uclass_{first,next}_device() but in copies with different name.

How do you know what the error was? If you return a 'dev' then how do you know whether it is OK to process it? I'd prefer that this is provided via the return value rather than checking device_active(), etc.

Quoted 4 lines

What use case is there for an incomplete enumeration as done by uclass_first_device() today? In order to continue enumeration devp needs to be set IIUC.

The existing API returns a NULL device when it gets an error, meaning that the device cannot be used. The use case is for devices which don't fail on probe. While I understand that removeable devices can fail to probe today and then succeed later, many devices are not like that, and failing to probe is an error.

Regards,
Simon

#37 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Am 19.04.2017 um 18:56 schrieb Simon Glass:

Quoted 82 lines

Hi Andreas,

Quoted 71 lines · Andreas Färber

Am 19.04.2017 um 17:52 schrieb Simon Glass:

Quoted 61 lines

Hi Andreas,

Quoted 46 lines · Simon Glass

Hi Andreas,

Quoted 22 lines · Andreas Färber

Hi Simon,

Am 19.04.2017 um 16:28 schrieb Simon Glass:

Quoted 19 lines · Heinrich Schuchardt
Quoted 17 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Quoted 5 lines
Quoted 3 lines

I would like to avoid changing the API that much. Can you please change it to stop calling the tail function and always set the device, like you did in v1?

I fear you're missing the key point I made in my lengthy explanation:

That's not entirely impossible.

Quoted 5 lines

Our caller (EFI) wants to iterate over the available devices. SDIO is not available. If we return a non-NULL device it will try to scan the disk. Therefore I think v2 is more correct (not yet tested).

Quoted 7 lines

So really the question is what your desired semantics of this function are and how callers here and elsewhere are handling it. If we want to return non-probed devices to the caller, as you now suggest, then we would need to audit and amend all callers of the API with some "if !is_probed() then continue" check. If we simply skip them internally, as done here IIUC, we require no changes on the caller side, thus much less invasive.

Quoted 8 lines

Well the value of 'ret' gives you that information if you want it. But yes it is a change and on second thoughts I'm not entirely comfortable with it.

Quoted 4 lines

Maybe we need a new API uclass_{first,next}_available_device() to make this clear? The change would then only affect callers of the new API, and EFI and possibly others would again need to be audited and updated.

If you think this is generally useful then you could add this. I think it would be something like:

Quoted 8 lines

for (ret = uclass_first_avail_device(UCLASS_..., &dev; dev; ret =

uclass_next_avail_device(&dev)) {
    if (!ret) {
       // do something

}
}

Does that sounds right?

Quoted 7 lines

No. I think that should be the semantics of uclass_first_device(), i.e. Heinrich's v1, possibly moved out of _tail() as you requested.

The idea behind a separate ..._available_device() implementation was to not have to do that ret check and to simply replace the function name to change the semantics, i.e. Heinrich's v2 implementation, but not inside uclass_{first,next}_device() but in copies with different name.

Quoted 4 lines

How do you know what the error was? If you return a 'dev' then how do you know whether it is OK to process it? I'd prefer that this is provided via the return value rather than checking device_active(), etc.

You misunderstand: That ret handling should be hidden inside _available_device, not exposed to its caller! :)

Note that v2 adds a for loop inside both functions!

So the caller only sees the devices that probed and would never see a non-zero ret, i.e. they could become void (or return the dev, which would change the calling convention).

Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#38 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Hi Andreas,

Quoted 88 lines · Andreas F채rber

Am 19.04.2017 um 18:56 schrieb Simon Glass:

Quoted 82 lines

Hi Andreas,

Quoted 71 lines · Andreas F채rber

Am 19.04.2017 um 17:52 schrieb Simon Glass:

Quoted 61 lines

Hi Andreas,

Quoted 46 lines · Simon Glass

Hi Andreas,

Quoted 22 lines · Andreas F채rber

Hi Simon,

Am 19.04.2017 um 16:28 schrieb Simon Glass:

Quoted 19 lines · Heinrich Schuchardt
Quoted 17 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas F채rber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Quoted 5 lines
Quoted 3 lines

I would like to avoid changing the API that much. Can you please change it to stop calling the tail function and always set the device, like you did in v1?

I fear you're missing the key point I made in my lengthy explanation:

That's not entirely impossible.

Quoted 5 lines

Our caller (EFI) wants to iterate over the available devices. SDIO is not available. If we return a non-NULL device it will try to scan the disk. Therefore I think v2 is more correct (not yet tested).

Quoted 7 lines

So really the question is what your desired semantics of this function are and how callers here and elsewhere are handling it. If we want to return non-probed devices to the caller, as you now suggest, then we would need to audit and amend all callers of the API with some "if !is_probed() then continue" check. If we simply skip them internally, as done here IIUC, we require no changes on the caller side, thus much less invasive.

Quoted 8 lines

Well the value of 'ret' gives you that information if you want it. But yes it is a change and on second thoughts I'm not entirely comfortable with it.

Quoted 4 lines

Maybe we need a new API uclass_{first,next}_available_device() to make this clear? The change would then only affect callers of the new API, and EFI and possibly others would again need to be audited and updated.

If you think this is generally useful then you could add this. I think it would be something like:

Quoted 8 lines

for (ret = uclass_first_avail_device(UCLASS_..., &dev; dev; ret =

uclass_next_avail_device(&dev)) {
    if (!ret) {
       // do something

}
}

Does that sounds right?

Quoted 7 lines

No. I think that should be the semantics of uclass_first_device(), i.e. Heinrich's v1, possibly moved out of _tail() as you requested.

The idea behind a separate ..._available_device() implementation was to not have to do that ret check and to simply replace the function name to change the semantics, i.e. Heinrich's v2 implementation, but not inside uclass_{first,next}_device() but in copies with different name.

Quoted 4 lines

How do you know what the error was? If you return a 'dev' then how do you know whether it is OK to process it? I'd prefer that this is provided via the return value rather than checking device_active(), etc.

Quoted 8 lines

You misunderstand: That ret handling should be hidden inside _available_device, not exposed to its caller! :)

Note that v2 adds a for loop inside both functions!

So the caller only sees the devices that probed and would never see a non-zero ret, i.e. they could become void (or return the dev, which would change the calling convention).

I see, so you want a 'higher level' function that only returns devices which probe without error. Then if you want to report the errors you would have to iterate in a different way. Is that right? So the return value would always be 0, right? Or would you make the function return the device pointer directly?

I am not very keen on this sort of function, since I suspect it would be useful only rarely. But I might be wrong and if you want to put it in, please go ahead.

BTW another point I should have made, is that really this sort of thing should be handled dynamically as needed. The EFI loader should not build its own tables parallel to DM. For example, if I run grub and then insert an MMC card or USB stick, grub won't know about it, right?

Regards,
Simon

#39 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Quoted 100 lines · Simon Glass

Hi Andreas,

Quoted 88 lines · Andreas Färber

Am 19.04.2017 um 18:56 schrieb Simon Glass:

Quoted 82 lines

Hi Andreas,

Quoted 71 lines · Andreas Färber

Am 19.04.2017 um 17:52 schrieb Simon Glass:

Quoted 61 lines

Hi Andreas,

Quoted 46 lines · Simon Glass

Hi Andreas,

Quoted 22 lines · Andreas Färber

Hi Simon,

Am 19.04.2017 um 16:28 schrieb Simon Glass:

Quoted 19 lines · Heinrich Schuchardt
Quoted 17 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Quoted 5 lines
Quoted 3 lines

I would like to avoid changing the API that much. Can you please change it to stop calling the tail function and always set the device, like you did in v1?

I fear you're missing the key point I made in my lengthy explanation:

That's not entirely impossible.

Quoted 5 lines

Our caller (EFI) wants to iterate over the available devices. SDIO is not available. If we return a non-NULL device it will try to scan the disk. Therefore I think v2 is more correct (not yet tested).

Quoted 7 lines

So really the question is what your desired semantics of this function are and how callers here and elsewhere are handling it. If we want to return non-probed devices to the caller, as you now suggest, then we would need to audit and amend all callers of the API with some "if !is_probed() then continue" check. If we simply skip them internally, as done here IIUC, we require no changes on the caller side, thus much less invasive.

Quoted 8 lines

Well the value of 'ret' gives you that information if you want it. But yes it is a change and on second thoughts I'm not entirely comfortable with it.

Quoted 4 lines

Maybe we need a new API uclass_{first,next}_available_device() to make this clear? The change would then only affect callers of the new API, and EFI and possibly others would again need to be audited and updated.

If you think this is generally useful then you could add this. I think it would be something like:

Quoted 8 lines

for (ret = uclass_first_avail_device(UCLASS_..., &dev; dev; ret =

uclass_next_avail_device(&dev)) {
    if (!ret) {
       // do something

}
}

Does that sounds right?

Quoted 7 lines

No. I think that should be the semantics of uclass_first_device(), i.e. Heinrich's v1, possibly moved out of _tail() as you requested.

The idea behind a separate ..._available_device() implementation was to not have to do that ret check and to simply replace the function name to change the semantics, i.e. Heinrich's v2 implementation, but not inside uclass_{first,next}_device() but in copies with different name.

Quoted 4 lines

How do you know what the error was? If you return a 'dev' then how do you know whether it is OK to process it? I'd prefer that this is provided via the return value rather than checking device_active(), etc.

Quoted 8 lines

You misunderstand: That ret handling should be hidden inside _available_device, not exposed to its caller! :)

Note that v2 adds a for loop inside both functions!

So the caller only sees the devices that probed and would never see a non-zero ret, i.e. they could become void (or return the dev, which would change the calling convention).

Quoted 5 lines

I see, so you want a 'higher level' function that only returns devices which probe without error. Then if you want to report the errors you would have to iterate in a different way. Is that right? So the return value would always be 0, right? Or would you make the function return the device pointer directly?

uclass_first_device and uclass_next_device are these "higher level"
functions: they return only devices probing without error. Unfortunately in some circumstances they do not return all devices. As Álvaro pointed out this bug is a pain in other places too.

This is what my patch fixes. There is no need for any new function.

Quoted 10 lines

I am not very keen on this sort of function, since I suspect it would be useful only rarely. But I might be wrong and if you want to put it in, please go ahead.

BTW another point I should have made, is that really this sort of thing should be handled dynamically as needed. The EFI loader should not build its own tables parallel to DM. For example, if I run grub and then insert an MMC card or USB stick, grub won't know about it, right?

According to the UEFI standard EFI_BOOT_SERVICES.LocateHandle() can be called until boot services are terminated.

You could create the drivers tables when this call occurs.

The current implementation first builds lists of all drivers and then calls the executable.

Rewriting this is probably a big job.

Best regards

Heinrich Schuchardt

Quoted 4 lines

Regards,
Simon

#40 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Quoted 107 lines · Heinrich Schuchardt
Quoted 100 lines · Simon Glass

Hi Andreas,

Quoted 88 lines · Andreas Färber

Am 19.04.2017 um 18:56 schrieb Simon Glass:

Quoted 82 lines

Hi Andreas,

Quoted 71 lines · Andreas Färber

Am 19.04.2017 um 17:52 schrieb Simon Glass:

Quoted 61 lines

Hi Andreas,

Quoted 46 lines · Simon Glass

Hi Andreas,

Quoted 22 lines · Andreas Färber

Hi Simon,

Am 19.04.2017 um 16:28 schrieb Simon Glass:

Quoted 19 lines · Heinrich Schuchardt
Quoted 17 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Quoted 5 lines
Quoted 3 lines

I would like to avoid changing the API that much. Can you please change it to stop calling the tail function and always set the device, like you did in v1?

I fear you're missing the key point I made in my lengthy explanation:

That's not entirely impossible.

Quoted 5 lines

Our caller (EFI) wants to iterate over the available devices. SDIO is not available. If we return a non-NULL device it will try to scan the disk. Therefore I think v2 is more correct (not yet tested).

Quoted 7 lines

So really the question is what your desired semantics of this function are and how callers here and elsewhere are handling it. If we want to return non-probed devices to the caller, as you now suggest, then we would need to audit and amend all callers of the API with some "if !is_probed() then continue" check. If we simply skip them internally, as done here IIUC, we require no changes on the caller side, thus much less invasive.

Quoted 8 lines

Well the value of 'ret' gives you that information if you want it. But yes it is a change and on second thoughts I'm not entirely comfortable with it.

Quoted 4 lines

Maybe we need a new API uclass_{first,next}_available_device() to make this clear? The change would then only affect callers of the new API, and EFI and possibly others would again need to be audited and updated.

If you think this is generally useful then you could add this. I think it would be something like:

Quoted 8 lines

for (ret = uclass_first_avail_device(UCLASS_..., &dev; dev; ret =

uclass_next_avail_device(&dev)) {
    if (!ret) {
       // do something

}
}

Does that sounds right?

Quoted 7 lines

No. I think that should be the semantics of uclass_first_device(), i.e. Heinrich's v1, possibly moved out of _tail() as you requested.

The idea behind a separate ..._available_device() implementation was to not have to do that ret check and to simply replace the function name to change the semantics, i.e. Heinrich's v2 implementation, but not inside uclass_{first,next}_device() but in copies with different name.

Quoted 4 lines

How do you know what the error was? If you return a 'dev' then how do you know whether it is OK to process it? I'd prefer that this is provided via the return value rather than checking device_active(), etc.

Quoted 8 lines

You misunderstand: That ret handling should be hidden inside _available_device, not exposed to its caller! :)

Note that v2 adds a for loop inside both functions!

So the caller only sees the devices that probed and would never see a non-zero ret, i.e. they could become void (or return the dev, which would change the calling convention).

Quoted 5 lines

I see, so you want a 'higher level' function that only returns devices which probe without error. Then if you want to report the errors you would have to iterate in a different way. Is that right? So the return value would always be 0, right? Or would you make the function return the device pointer directly?

Quoted 6 lines

uclass_first_device and uclass_next_device are these "higher level"
functions: they return only devices probing without error. Unfortunately in some circumstances they do not return all devices. As Álvaro pointed out this bug is a pain in other places too.

This is what my patch fixes. There is no need for any new function.

I do not what uclass_first/next_device to skip devices that don't probe. We need to have new functions.

This discussion seems to be going into the weeds. I'll see if I can work up a few patches and some tests to verify things.

Quoted 15 lines
Quoted 11 lines

I am not very keen on this sort of function, since I suspect it would be useful only rarely. But I might be wrong and if you want to put it in, please go ahead.

BTW another point I should have made, is that really this sort of thing should be handled dynamically as needed. The EFI loader should not build its own tables parallel to DM. For example, if I run grub and then insert an MMC card or USB stick, grub won't know about it, right?

According to the UEFI standard EFI_BOOT_SERVICES.LocateHandle() can be called until boot services are terminated.

Quoted 6 lines

You could create the drivers tables when this call occurs.

The current implementation first builds lists of all drivers and then calls the executable.

Rewriting this is probably a big job.

(this is off-topic from this patch but let me continue :-)

Actually this is how it should have been done in the first place IMO. Since everything is moving to driver model, it doesn't make a lot of sense to design EFI on the pre-driver-model approach.

I think implementing this for the boot-time interface is pretty easy, and I did in fact point this out in the original code review. However for the run-time interface, it is potentially quite painful, which has also already been discussed.

Regards,
Simon

#41 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

In reply to Simon Glass
Quoted 17 lines · Simon Glass

Hi Heinrich,

Quoted 14 lines · Heinrich Schuchardt

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

Quoted 7 lines
Quoted 3 lines

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

I would like to avoid changing the API that much. Can you please change it to stop calling the tail function and always set the device, like you did in v1?

Hello Simon,

with the patch nothing changes if the the available devices an contiguous starting at index 0.

Not calling the tail function would really change the API function in all cases. So why would we want to do so?

The current behavior is to stop at the first device that cannot be probed. Which use of uclass_first_device/uclass_next_device do you see in the U-Boot code that would benefit from this?

Quoted 4 lines

Also don't forget to add a test for this bahaviour. You may need to have sandbox device that returns an error when probing. Perhaps add another compatible string to denx,u-boot-fdt-test?

I will give it a try.

Best regards

Heinrich

Quoted 24 lines
Quoted 16 lines

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

Quoted 4 lines
---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)

Regards,
Simon

#42 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Hi Heinrih,

Quoted 38 lines · Heinrich Schuchardt
Quoted 17 lines · Simon Glass

Hi Heinrich,

Quoted 14 lines · Heinrich Schuchardt

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

Quoted 7 lines
Quoted 3 lines

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

I would like to avoid changing the API that much. Can you please change it to stop calling the tail function and always set the device, like you did in v1?

Hello Simon,

with the patch nothing changes if the the available devices an contiguous starting at index 0.

Not calling the tail function would really change the API function in all cases. So why would we want to do so?

The current behavior is to stop at the first device that cannot be probed. Which use of uclass_first_device/uclass_next_device do you see in the U-Boot code that would benefit from this?

Quoted 1 line
Quoted 5 lines
Quoted 3 lines

Also don't forget to add a test for this bahaviour. You may need to have sandbox device that returns an error when probing. Perhaps add another compatible string to denx,u-boot-fdt-test?

I will give it a try.

See my follow-up replies. I don't think we should change that function, actually.

Quoted 30 lines

Best regards

Heinrich

Quoted 24 lines
Quoted 16 lines

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

Quoted 4 lines
---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)

Regards,
Simon

#43 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

In reply to Heinrich Schuchardt

In case you decide to apply this version (I see you're yet deciding which is the best way to go), I tested it and it solves my problem with sysreset not bein probed correctly.

So,

Quoted 108 lines · Heinrich Schuchardt

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
	status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)
drivers/core/uclass.c +33 -11
index 04fb45b..cff3a3f 100644
@@ -420,16 +420,30 @@ int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent,
 }
 #endif
 
+/**
+ * uclass_first_device() - Finds first device of an uclass that can be probed
+ * @id: uclass id
+ * @devp: device found or NULL
+ * @return always 0
+ *
+ * For iterating over all devices of an uclass use
+ * for(uclass_first_device(id, &dev); dev; uclass_next_device(&dev)).
+ */
 int uclass_first_device(enum uclass_id id, struct udevice **devp)
 {
 	struct udevice *dev;
-	int ret;
 
 	*devp = NULL;
-	ret = uclass_find_first_device(id, &dev);
-	if (!dev)
-		return 0;
-	return uclass_get_device_tail(dev, ret, devp);
+	for (uclass_find_first_device(id, &dev); dev;
+	     uclass_find_next_device(&dev)) {
+
+		uclass_get_device_tail(dev, 0, devp);
+		if (*devp)
+			break;
+	}
+	debug("%s(%d): %s\n", __func__, id, dev ? dev->name : "(EOL)");
+
+	return 0;
 }
 
 int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
@@ -445,16 +459,24 @@ int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
 	return 0;
 }
 
+/**
+ * uclass_next_device() - Find next device of an uclass that can be probed
+ * @devp: device found or NULL
+ * @return always 0
+ */
 int uclass_next_device(struct udevice **devp)
 {
 	struct udevice *dev = *devp;
-	int ret;
 
-	*devp = NULL;
-	ret = uclass_find_next_device(&dev);
-	if (!dev)
-		return 0;
-	return uclass_get_device_tail(dev, ret, devp);
+	for (*devp = NULL; !*devp; ) {
+		uclass_find_next_device(&dev);
+		if (!dev)
+			break;
+		uclass_get_device_tail(dev, 0, devp);
+	}
+	debug("%s: %s\n", __func__, dev ? dev->name : "(EOL)");
+
+	return 0;
 }
 
 int uclass_bind_device(struct udevice *dev)
#44 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Am 19.04.2017 um 18:22 schrieb Álvaro Fernández Rojas:

Quoted 1 line

In case you decide to apply this version (I see you're yet deciding which is the best way to go), I tested it and it solves my problem with sysreset not bein probed correctly.

Can you point us to which call site that is in your case exactly?

Thanks,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#45 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Hi Andreas,

Quoted 4 lines · Andreas Färber

Am 19.04.2017 um 18:22 schrieb Álvaro Fernández Rojas:

Quoted 1 line

In case you decide to apply this version (I see you're yet deciding which is the best way to go), I tested it and it solves my problem with sysreset not bein probed correctly.

Can you point us to which call site that is in your case exactly?

Sure, see: https://github.com/Noltari/u-boot/commits/bmips-next-v3-fixes
And: https://lists.denx.de/pipermail/u-boot/2017-April/288041.html

Quoted 4 lines

Thanks,
Andreas

Regards,
Álvaro.

#46 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Am 19.04.2017 um 18:31 schrieb Álvaro Fernández Rojas:

Quoted 9 lines

Hi Andreas,

Quoted 4 lines · Andreas Färber

Am 19.04.2017 um 18:22 schrieb Álvaro Fernández Rojas:

Quoted 1 line

In case you decide to apply this version (I see you're yet deciding which is the best way to go), I tested it and it solves my problem with sysreset not bein probed correctly.

Can you point us to which call site that is in your case exactly?

Sure, see: https://github.com/Noltari/u-boot/commits/bmips-next-v3-fixes
And: https://lists.denx.de/pipermail/u-boot/2017-April/288041.html

https://lists.denx.de/pipermail/u-boot/2017-April/288091.html

Hmm, to me that looks like the exact opposite symptom of what we're discussing right now. You seem to be getting into the for loop and adding checks there, whereas our issue is that we're not getting into the for loop due to NULL dev.

IIUC your code would be another candidate for _available_device() under discussion, as your patch is skipping devices that don't probe.

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#47 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

In reply to Heinrich Schuchardt

Am 19.04.2017 um 13:26 schrieb Heinrich Schuchardt:

Quoted 3 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being

"bootefi"

Quoted 29 lines

passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
	status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

Quoted 3 lines
---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)

Confirming that on my Vega S95 Telos this results in a full GRUB menu, and GRUB sees two disks.

Many thanks,

Andreas

## Starting application at 0x01000000 ...

U-Boot 2017.05-rc2-00063-gfc365a8 (Apr 19 2017 - 22:48:23 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 44 ms (451.2 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 12 ms (10.3 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1806
Scanning disk mmc at 72000.blk...
About to add disk device 'mmc at 72000.blk'
Adding disk device 'mmc at 72000.blk'
** First descriptor is NOT a primary desc on 2:1 ** Scanning disk mmc at 74000.blk...
About to add disk device 'mmc at 74000.blk'
Adding disk device 'mmc at 74000.blk'
Found 2 disks
Welcome to GRUB!

[...]

grub>ls
(hd0) (hd0,msdos2) (hd0,msdos1) (hd1)

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#48 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Quoted 43 lines · Andreas Färber

Am 19.04.2017 um 13:26 schrieb Heinrich Schuchardt:

Quoted 3 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being

"bootefi"

Quoted 29 lines

passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
      status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

Quoted 3 lines
---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)
Quoted 6 lines

Confirming that on my Vega S95 Telos this results in a full GRUB menu, and GRUB sees two disks.

Many thanks,

Andreas

Just to be clear, I am NAKing this patch. I do not want to change the existing semantics as it requires existing code to check the function return value. Instead I would like to:

- Fix the bug found by Alvaro
https://lists.denx.de/pipermail/u-boot/2017-April/288091.html This involves setting *devp to NULL when returning an error.
- Add two new functions which return the device whether it probes or not, allowing iteration to continue. Since we have two potential users for these functions, it seems worth it.

I'll take a look at this soon unless someone else does :-)

Regards,
SImon

Quoted 50 lines

## Starting application at 0x01000000 ...

U-Boot 2017.05-rc2-00063-gfc365a8 (Apr 19 2017 - 22:48:23 +0200) vega-s95

DRAM:  2 GiB
MMC:   mmc at 70000: 0, mmc at 72000: 1, mmc at 74000: 2

Using default environment

In:    serial at 4c0
Out:   serial at 4c0
Err:   serial at 4c0
Net:   eth0: ethernet at c9410000
Hit any key to stop autoboot:  0
mmc_init: -95, time 1806

MMC Device 0 not found
no mmc device at slot 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Setting boot device name to '//boot/dtb/amlogic/meson-gxbb-v' 20335 bytes read in 44 ms (451.2 KiB/s)
Found EFI removable media binary efi/boot/bootaa64.efi Setting boot device name to '/efi/boot/bootaa64.efi' reading efi/boot/bootaa64.efi
129024 bytes read in 12 ms (10.3 MiB/s)
## Starting EFI application at 01080000 ...
mmc_init: -95, time 1806
Scanning disk mmc at 72000.blk...
About to add disk device 'mmc at 72000.blk'
Adding disk device 'mmc at 72000.blk'
** First descriptor is NOT a primary desc on 2:1 ** Scanning disk mmc at 74000.blk...
About to add disk device 'mmc at 74000.blk'
Adding disk device 'mmc at 74000.blk'
Found 2 disks
Welcome to GRUB!

[...]

grub>ls
(hd0) (hd0,msdos2) (hd0,msdos1) (hd1)

--
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton HRB 21284 (AG Nürnberg)

#49 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Hi,

Quoted 55 lines · Simon Glass
Quoted 43 lines · Andreas Färber

Am 19.04.2017 um 13:26 schrieb Heinrich Schuchardt:

Quoted 3 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being

"bootefi"

Quoted 29 lines

passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
      status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

Quoted 3 lines
---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)
Quoted 6 lines

Confirming that on my Vega S95 Telos this results in a full GRUB menu, and GRUB sees two disks.

Many thanks,

Andreas

Just to be clear, I am NAKing this patch. I do not want to change the existing semantics as it requires existing code to check the function return value. Instead I would like to:

Quoted 8 lines

- Fix the bug found by Alvaro
https://lists.denx.de/pipermail/u-boot/2017-April/288091.html This involves setting *devp to NULL when returning an error.
- Add two new functions which return the device whether it probes or not, allowing iteration to continue. Since we have two potential users for these functions, it seems worth it.

I'll take a look at this soon unless someone else does :-)

Here is my attempt:

http://patchwork.ozlabs.org/patch/752578/
http://patchwork.ozlabs.org/patch/752576/
http://patchwork.ozlabs.org/patch/752577/

Regards,
Simon
[...]

#50 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Am 23.04.2017 um 01:58 schrieb Simon Glass:

Quoted 65 lines

Hi,

Quoted 62 lines · Simon Glass
Quoted 43 lines · Andreas Färber

Am 19.04.2017 um 13:26 schrieb Heinrich Schuchardt:

Quoted 3 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being

"bootefi"

Quoted 29 lines

passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
      status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

Quoted 3 lines
---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)
Quoted 6 lines

Confirming that on my Vega S95 Telos this results in a full GRUB menu, and GRUB sees two disks.

Many thanks,

Andreas

Just to be clear, I am NAKing this patch. I do not want to change the existing semantics as it requires existing code to check the function return value. Instead I would like to:

- Fix the bug found by Alvaro
https://lists.denx.de/pipermail/u-boot/2017-April/288091.html This involves setting *devp to NULL when returning an error.
- Add two new functions which return the device whether it probes or not, allowing iteration to continue. Since we have two potential users for these functions, it seems worth it.

Quoted 7 lines
Quoted 1 line

I'll take a look at this soon unless someone else does :-)

Here is my attempt:

http://patchwork.ozlabs.org/patch/752578/
http://patchwork.ozlabs.org/patch/752576/
http://patchwork.ozlabs.org/patch/752577/

You have taken my idea with s/available/ok/ and Heinrich's v2 loop implementation and posted it without Suggested-by or Signed-off-by. :(

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#51 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Hi Andreas,

Quoted 68 lines · Andreas Färber

Am 23.04.2017 um 01:58 schrieb Simon Glass:

Quoted 67 lines

Hi,

Quoted 63 lines · Simon Glass
Quoted 43 lines · Andreas Färber

Am 19.04.2017 um 13:26 schrieb Heinrich Schuchardt:

Quoted 3 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being

"bootefi"

Quoted 29 lines

passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
      status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

Quoted 3 lines
---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)
Quoted 6 lines

Confirming that on my Vega S95 Telos this results in a full GRUB menu, and GRUB sees two disks.

Many thanks,

Andreas

Just to be clear, I am NAKing this patch. I do not want to change the existing semantics as it requires existing code to check the function return value. Instead I would like to:

- Fix the bug found by Alvaro
https://lists.denx.de/pipermail/u-boot/2017-April/288091.html This involves setting *devp to NULL when returning an error.
- Add two new functions which return the device whether it probes or not, allowing iteration to continue. Since we have two potential users for these functions, it seems worth it.

I'll take a look at this soon unless someone else does :-)

Quoted 8 lines
Quoted 5 lines

Here is my attempt:

http://patchwork.ozlabs.org/patch/752578/
http://patchwork.ozlabs.org/patch/752576/
http://patchwork.ozlabs.org/patch/752577/

You have taken my idea with s/available/ok/ and Heinrich's v2 loop implementation and posted it without Suggested-by or Signed-off-by. :(

Please send me what you would like and I'll add it.

I've had second (third?) thoughts on this so will be sending another version.

Regards,
Simon

#52 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

In reply to Simon Glass

Am 19.04.2017 um 23:34 schrieb Simon Glass:

Quoted 47 lines · Andreas Färber
Quoted 46 lines

Am 19.04.2017 um 13:26 schrieb Heinrich Schuchardt:

Quoted 3 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being

"bootefi"

Quoted 29 lines

passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
      status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

Quoted 3 lines
---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)

Confirming that on my Vega S95 Telos this results in a full GRUB menu, and GRUB sees two disks.

Quoted 7 lines
Quoted 3 lines

Many thanks,

Andreas

Just to be clear, I am NAKing this patch. I do not want to change the existing semantics as it requires existing code to check the function return value.

And to be clear I still think you are mistaken in holding on to an implementation that assumes that all devices will probe okay. We might be able to fix the issue at hand in different ways - be it at the callsite or by adding a new API - but this is papering over other potential problems in the codebase. Hardware might malfunction, drivers might not be implemented in U-Boot or be disabled by user's config, etc.

The caller might notice that some error has occurred by checking the return code, but what do you seriously expect it to do then? If it's supposed to call an alternative iteration function to continue, it could just call that in the first place.

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
#53 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Hi Andreas,

Quoted 50 lines · Andreas Färber

Am 19.04.2017 um 23:34 schrieb Simon Glass:

Quoted 49 lines · Andreas Färber
Quoted 48 lines

Am 19.04.2017 um 13:26 schrieb Heinrich Schuchardt:

Quoted 3 lines

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being

"bootefi"

Quoted 29 lines

passed to the EFI executable if the first device cannot be probed.

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
      status = "okay";
}

This device does not exist on the board and cannot be initialized.

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

Quoted 3 lines
---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)

Confirming that on my Vega S95 Telos this results in a full GRUB menu, and GRUB sees two disks.

Many thanks,

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

Andreas

Just to be clear, I am NAKing this patch. I do not want to change the existing semantics as it requires existing code to check the function return value.

And to be clear I still think you are mistaken in holding on to an implementation that assumes that all devices will probe okay.

The current API works pretty well and is used ~90 times in U-Boot so I'm reluctant to change it. In particular, having to check the return value to see if you can use dev or not would be a pretty significant change. I think there are some uses for it, but the majority of the time you want devices that work.

Quoted 4 lines

be able to fix the issue at hand in different ways - be it at the callsite or by adding a new API - but this is papering over other potential problems in the codebase. Hardware might malfunction, drivers might not be implemented in U-Boot or be disabled by user's config, etc.

This is up to the implementation, but for many boards if an expected device does not work then it is a problem. I suspect the main exception to this is removeable devices and situations where any of a number of boot paths might be chosen, some of which rely on removeable devices.

Anyway I'm not trying to mandate any one way of dealing with devices, just pointing out that the existing API works fairly well.

Quoted 5 lines

The caller might notice that some error has occurred by checking the return code, but what do you seriously expect it to do then? If it's supposed to call an alternative iteration function to continue, it could just call that in the first place.

In most cases, it would fail to boot and go to some sort of recovery mode. It often indicates a serious hardware error, and continuing is bad.

Having thought a bit more I think that ignoring errors is not a great way to go. So I'm going to update the series to try a different approach. Please can you reply to that with the tags you would like on it, or suggest another approach if you don't like it.

Regards,
Simon

#54 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

In reply to Heinrich Schuchardt

Hi Heinrick,

Quoted 5 lines · Heinrich Schuchardt

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

Quoted 8 lines

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

I just re-read this thread and saw this point again.

If this is not on the board, shouldn't the device have "disabled" in its node?

Quoted 19 lines

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

Quoted 3 lines
---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)

Regards,
Simon

#55 lore raw

PATCH v2 1/1 core/uclass: iterate over all devices of a uclass

Quoted 17 lines · Simon Glass

Hi Heinrick,

Quoted 5 lines · Heinrich Schuchardt

When iterating over the devices of an uclass the iteration stops at the first device that cannot be probed.
When calling booefi this will result in no block device being passed to the EFI executable if the first device cannot be probed.

Quoted 8 lines

The problem was reported by Andreas Färber in
https://lists.denx.de/pipermail/u-boot/2017-April/287432.html

For testing I used an odroid-c2 with a dts including

&sd_emmc_a {
        status = "okay";
}

This device does not exist on the board and cannot be initialized.

Quoted 4 lines

I just re-read this thread and saw this point again.

If this is not on the board, shouldn't the device have "disabled" in its node?

I wanted to reproduce the probkem Andreas had with his board.

In the U-Boot repository this device is disabled.

Best regards

Heinrich Schuchardt

Quoted 26 lines
Quoted 19 lines

With the patch uclass_first_device and uclass_next_device iterate internally until they find the first device that can be probed or the end of the device list is reached.

Debug output is provided for the two functions.

---
v2:
As suggested by Simon Glass correct uclass_first_device() and uclass_next_device() instead of uclass_get_device_tail() to avoid side effects.
v1:
The original patch was posted as
core/uclass: uclass_get_device_tail: always set devp
https://lists.denx.de/pipermail/u-boot/2017-April/288068.html

Quoted 3 lines
---
 drivers/core/uclass.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)

Regards,
Simon

#56 lore raw

PATCH v7 3/3 odroid-c2: enable new Meson GX MMC driver in board defconfig

In reply to Heiner Kallweit

Enable new Meson GX MMC driver in Odroid C2 defconfig.

---
v6:
- no changes
v7:
- rebased

---
 configs/odroid-c2_defconfig | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
configs/odroid-c2_defconfig +4 -1
index 2cf5011..00da76e 100644
@@ -14,7 +14,10 @@ CONFIG_DEFAULT_DEVICE_TREE="meson-gxbb-odroidc2"
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_OF_CONTROL=y
 CONFIG_NET_RANDOM_ETHADDR=y
-# CONFIG_MMC is not set
+CONFIG_MMC=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_MESON_GX=y
+CONFIG_CMD_MMC=y
 CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_PINCTRL=y
Signature · 1 line
2.12.2
#57 lore raw

PATCH v7 3/3 odroid-c2: enable new Meson GX MMC driver in board defconfig

Quoted 3 lines · Heiner Kallweit

Enable new Meson GX MMC driver in Odroid C2 defconfig.

Applied to u-boot-mmc. Thanks!

Best Regards,
Jaehoon Chung

Quoted 26 lines

---
v6:
- no changes
v7:
- rebased

---
 configs/odroid-c2_defconfig | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
configs/odroid-c2_defconfig +4 -1
index 2cf5011..00da76e 100644
@@ -14,7 +14,10 @@ CONFIG_DEFAULT_DEVICE_TREE="meson-gxbb-odroidc2"
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_OF_CONTROL=y
 CONFIG_NET_RANDOM_ETHADDR=y
-# CONFIG_MMC is not set
+CONFIG_MMC=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_MESON_GX=y
+CONFIG_CMD_MMC=y
 CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_PINCTRL=y
#58 lore raw

v7 cover mmc: meson: add MMC support for Meson GX (S905)

In reply to Heiner Kallweit

Hi Heiner,

Quoted 9 lines · Heiner Kallweit

This patch set implements eMMC on Amlogic Meson GX (S905). It's based on Carlo Caione's work submitted here:
http://lists.denx.de/pipermail/u-boot/2016-May/254391.html

Changes to the original version:
- BLK support added
- fully DT-based now
- minor general refactoring

Quoted 5 lines

The driver was successfully tested on a Odroid C2.

Note: On Odroid C2 eMMC is MMC device 1. So you have to switch from MMC device 0 to 1 first when testing from uboot prompt.

I'm not sure but i think that you can use the fixed index for eMMC. Maybe you can refer to below commit.

commit 02ad33aa3a84821c8d9a6c4f167f143f6248b084

Refs: v2017.03-rc1-170-g02ad33a
Author:     Jaehoon Chung <[email protected]>
AuthorDate: Thu Feb 2 13:41:14 2017 +0900
Commit:     Jaehoon Chung <[email protected]>
CommitDate: Thu Feb 9 20:37:05 2017 +0900

mmc: mmc-uclass: use the fixed devnum with alias node

If there are alias nodes as "mmc", use the devnum as alias index number.
This patch is for fixing a problem of Exynos4 series. Problem is the below thing.

Current legacy mode:
EXYNOS DWMMC: 0, SAMSUNG SDHCI: 1

After using DM:
SAMSUNG SDHCI: 0, EXYNOS DWMMC: 1

Dev index is swapped.
Then u-boot can't find the kernel image..because it is already set to 0 as mmcdev. If change from legacy to DM, also needs to touch all exynos4 config file. For using simply, just supporting the fixed devnum with alias node is better than it.

Usage:
alaise {
....
mmc0 = &sdhci2; /* eMMC */
mmc1 = &sdhci1; /* SD */
...
}

Anyway, I'm testing your patches with buildman..after that, i will apply.. But this patchset was delegated to Minkyu, so i will change it. if you are ok.

Best Regards,
Jaehoon Chung

Quoted 28 lines

Latest change in v7:
- rebase due to other recent mmc changes

Heiner Kallweit (3):
arm: dts: update Meson GXBB / Odroid-C2 DT with recent Linux version
mmc: meson: add MMC driver for Meson GX (S905)
odroid-c2: enable new Meson GX MMC driver in board defconfig

 arch/arm/dts/meson-gx.dtsi                | 447 +++++++++++++++++++
 arch/arm/dts/meson-gxbb-odroidc2.dts      | 147 +++++-
 arch/arm/dts/meson-gxbb.dtsi              | 718 ++++++++++++++++++------------
 arch/arm/include/asm/arch-meson/sd_emmc.h |  89 ++++
 configs/odroid-c2_defconfig               |   5 +-
 drivers/mmc/Kconfig                       |   6 +
 drivers/mmc/Makefile                      |   1 +
 drivers/mmc/meson_gx_mmc.c                | 291 ++++++++++++
 include/dt-bindings/clock/gxbb-aoclkc.h   |  66 +++
 include/dt-bindings/clock/gxbb-clkc.h     |  34 ++
 include/dt-bindings/reset/gxbb-aoclkc.h   |  66 +++
 11 files changed, 1594 insertions(+), 276 deletions(-)
 create mode 100644 arch/arm/dts/meson-gx.dtsi
 create mode 100644 arch/arm/include/asm/arch-meson/sd_emmc.h
 create mode 100644 drivers/mmc/meson_gx_mmc.c
 create mode 100644 include/dt-bindings/clock/gxbb-aoclkc.h
 create mode 100644 include/dt-bindings/clock/gxbb-clkc.h
 create mode 100644 include/dt-bindings/reset/gxbb-aoclkc.h