Browse Source

Merge branch '2019-08-11-ti-imports'

- More DaVinci updates and fixes
- PCIe support on am65x
- Watchdog converted to DM
- Assorted other bugfixes
Tom Rini 4 years ago
parent
commit
9c6115822e
47 changed files with 2850 additions and 59 deletions
  1. 1 0
      arch/arm/dts/Makefile
  2. 416 0
      arch/arm/dts/am335x-brsmarc1.dts
  3. 108 0
      arch/arm/dts/k3-am65-main.dtsi
  4. 1 0
      arch/arm/dts/k3-am65.dtsi
  5. 5 0
      arch/arm/include/asm/ti-common/omap_wdt.h
  6. 16 5
      arch/arm/mach-k3/sysfw-loader.c
  7. 1 0
      arch/arm/mach-omap2/Kconfig
  8. 4 0
      arch/arm/mach-omap2/am33xx/Kconfig
  9. 1 1
      arch/arm/mach-omap2/boot-common.c
  10. 15 0
      board/BuR/brsmarc1/Kconfig
  11. 6 0
      board/BuR/brsmarc1/MAINTAINERS
  12. 10 0
      board/BuR/brsmarc1/Makefile
  13. 168 0
      board/BuR/brsmarc1/board.c
  14. 33 0
      board/BuR/brsmarc1/config.mk
  15. 266 0
      board/BuR/brsmarc1/mux.c
  16. 2 1
      board/davinci/da8xxevm/da850evm.c
  17. 26 0
      board/overo/common.c
  18. 0 14
      board/overo/overo.c
  19. 107 17
      board/siemens/common/factoryset.c
  20. 3 0
      board/siemens/common/factoryset.h
  21. 3 0
      configs/am335x_evm_defconfig
  22. 8 0
      configs/am65x_evm_a53_defconfig
  23. 109 0
      configs/brsmarc1_defconfig
  24. 11 6
      configs/da850evm_direct_nor_defconfig
  25. 13 0
      drivers/clk/clk-uclass.c
  26. 17 0
      drivers/core/fdtaddr.c
  27. 20 0
      drivers/core/read.c
  28. 10 3
      drivers/firmware/ti_sci.c
  29. 6 0
      drivers/pci/Kconfig
  30. 1 0
      drivers/pci/Makefile
  31. 725 0
      drivers/pci/pcie_dw_ti.c
  32. 9 0
      drivers/phy/Kconfig
  33. 1 0
      drivers/phy/Makefile
  34. 411 0
      drivers/phy/phy-ti-am654.c
  35. 4 4
      drivers/power/domain/ti-sci-power-domain.c
  36. 8 1
      drivers/watchdog/Kconfig
  37. 1 0
      drivers/watchdog/Makefile
  38. 121 0
      drivers/watchdog/omap_wdt.c
  39. 12 0
      include/clk.h
  40. 83 0
      include/configs/brsmarc1.h
  41. 2 2
      include/configs/da850evm.h
  42. 18 0
      include/dm/fdtaddr.h
  43. 41 0
      include/dm/read.h
  44. 13 0
      include/dt-bindings/phy/phy-am654-serdes.h
  45. 1 1
      include/watchdog.h
  46. 1 0
      test/dm/clk.c
  47. 12 4
      test/dm/test-fdt.c

+ 1 - 0
arch/arm/dts/Makefile

@@ -282,6 +282,7 @@ dtb-$(CONFIG_AM33XX) += \
 	am335x-brppt1-nand.dtb \
 	am335x-brppt1-spi.dtb \
 	am335x-brxre1.dtb \
+	am335x-brsmarc1.dtb \
 	am335x-draco.dtb \
 	am335x-evm.dtb \
 	am335x-evmsk.dtb \

+ 416 - 0
arch/arm/dts/am335x-brsmarc1.dts

@@ -0,0 +1,416 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 B&R Industrial Automation GmbH
+ * http://www.br-automation.com
+ *
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "dt-bindings/thermal/thermal.h"
+
+/ {
+	model = "BRSMARC1 SoM";
+	compatible = "ti,am33xx";
+
+	fset: factory-settings {
+		bl-version	= "                                ";
+		order-no	= "                                ";
+		cpu-order-no	= "                                ";
+		hw-revision	= "                                ";
+		serial-no	= <0>;
+		device-id	= <0x0>;
+		parent-id	= <0x0>;
+		hw-variant	= <0x0>;
+		hw-platform	= <0x7>;
+		fram-offset	= <0x100>;
+		fram-size	= <0x1F00>;
+		cache-disable	= <0x0>;
+		cpu-clock	= <0x0>;
+	};
+
+	chosen {
+		bootargs = "console=ttyO0,115200 earlyprintk";
+		stdout-path = &uart0;
+	};
+
+	aliases {
+		fset = &fset;
+		mmc = &mmc2;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		touch0 = &burtouch0;
+		screen0 = &lcdscreen0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	vmmcsd_fixed: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	lcdscreen0: lcdscreen@0 {
+		/*backlight = <&tps_bl>; */
+		compatible = "ti,tilcdc,panel";
+		status = "okay";
+
+		panel-info {
+			ac-bias		= <255>;
+			ac-bias-intrpt	= <0>;
+			dma-burst-sz	= <16>;
+			bpp		= <32>;
+			fdd		= <0x80>;
+			sync-edge	= <0>;
+			sync-ctrl	= <1>;
+			raster-order	= <0>;
+			fifo-th		= <0>;
+			rotation	= <0>;
+			pupdelay	= <0>;
+			pondelay	= <0>;
+			pwrpin		= <0x000000B1>;
+			brightdrv	= <0>;
+			brightfdim	= <100>;
+			brightdef	= <50>;
+		};
+
+		display-timings {
+			default {
+				clock-frequency	= <0>;
+				hactive		= <0>;
+				vactive		= <0>;
+				hfront-porch	= <0>;
+				hback-porch	= <0>;
+				hsync-len	= <0>;
+				vfront-porch	= <0>;
+				vback-porch	= <0>;
+				vsync-len	= <0>;
+				hsync-active	= <0>;
+				vsync-active	= <0>;
+				pupdelay	= <10>;
+				pondelay	= <10>;
+			};
+		};
+	};
+
+	board_thermal: board-thermal {
+		polling-delay-passive = <1000>; /* milliseconds */
+		polling-delay = <2500>; /* milliseconds */
+
+		thermal-sensors = <&cputemp>;
+
+		trips {
+			crit_trip: crit-trip {
+				temperature = <95000>; /* millicelsius */
+				hysteresis = <5000>; /* millicelsius */
+				type = "critical";
+			};
+		};
+		cooling-maps {
+			map0 {
+				trip = <&crit_trip>;
+				cooling-device =
+				<&resetc THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+			};
+		};
+	};
+};
+
+&uart0 {		/* console uart */
+	u-boot,dm-spl;
+	status = "okay";
+};
+
+&uart2 {		/* X2X - P2P */
+	status = "okay";
+};
+
+&uart3 {		/* RS485 */
+	status = "okay";
+};
+
+&uart4 {		/* RS232 */
+	status = "okay";
+};
+
+&i2c0 {
+	u-boot,dm-spl;
+	status = "okay";
+	clock-frequency = <100000>;
+
+	tps: tps@24 {		/* PMIC controller */
+		u-boot,dm-spl;
+		reg = <0x24>;
+		compatible = "ti,tps65217";
+	};
+
+	cputemp: temperature-sensor@48 {	/* cpu temperature */
+		#thermal-sensor-cells = <0>;
+		compatible = "nxp,pct2075";
+		reg = <0x48>;
+	};
+
+	basetemp: temperature-sensor@49 {	/* baseboard temperature */
+		#thermal-sensor-cells = <0>;
+		compatible = "nxp,pct2075";
+		reg = <0x49>;
+	};
+	extrtc: rtc@51 {	/* realtime clock */
+		compatible = "epson,rx8571";
+		reg = <0x51>;
+	};
+
+	resetc: reset-controller@60 {
+		compatible = "bur,rststm";
+		reg = <0x60>;
+
+		cooling-min-state = <0>;
+		cooling-max-state = <1>;	/* reset gets fired */
+		#cooling-cells = <2>;		/* min followed by max */
+	};
+};
+
+&i2c1 {
+	u-boot,dm-spl;
+	status = "okay";
+};
+
+&spi0 {
+	u-boot,dm-spl;
+	status = "okay";
+
+	cs-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>,
+		   <&gpio0 6 GPIO_ACTIVE_HIGH>,
+		   <0>,
+		   <0>;
+
+	spi-max-frequency = <24000000>;
+
+	spi_flash: spiflash@0 {
+		u-boot,dm-spl;
+		u-boot,dm-pre-reloc;
+		compatible = "spidev", "spi-flash";
+		spi-max-frequency = <24000000>;
+		reg = <0>;
+	};
+};
+
+&spi1 {
+	u-boot,dm-spl;
+	status = "okay";
+	cs-gpios = <&gpio3 17 GPIO_ACTIVE_HIGH>,
+		   <&gpio0 19 GPIO_ACTIVE_HIGH>,
+		   <0>,
+		   <0>;
+
+	spi-max-frequency = <24000000>;
+};
+
+&edma {
+	status = "okay";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&davinci_mdio {
+	status = "okay";
+};
+
+&mac {
+	status = "okay";
+};
+
+&phy_sel {
+	rmii-clock-ext;
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rmii";
+	ti,ledcr = <0x0480>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <3>;
+	phy-mode = "rmii";
+	ti,ledcr = <0x0480>;
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <0x4>;
+	ti,non-removable;
+	ti,needs-special-hs-handling;
+	ti,vcc-aux-disable-is-sleep;
+	status = "okay";
+};
+
+&mmc2 {
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <0x8>;
+	ti,non-removable;
+	ti,needs-special-hs-handling;
+	ti,vcc-aux-disable-is-sleep;
+	status = "okay";
+};
+
+&lcdc {
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&elm {
+	status = "okay";
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&gpio0 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&gpio1 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&gpio2 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&gpio3 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&timer1 {		/* today unused */
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&timer2 {		/* used for vxworks primary timer device */
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&timer3 {		/* used sysdelay and hal tsc counter*/
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&timer4 {		/* used for PWM beeper */
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&timer5 {		/* used for PWM backlight */
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&timer6 {		/* used for cpsw end device */
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&timer7 {		/* used for cpsw end device */
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&wdt2 {
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&epwmss0 {
+	status = "okay";
+};
+
+&tscadc {
+	status = "okay";
+
+	tsc {
+		burtouch0: burtouch@0 {
+			status = "okay";
+			compatible = "bur,DdVxSfTouchXXX";
+			bur,hwtree = "IF7";
+			bur,KX0 = <0x0>;
+			bur,KX1 = <0x0>;
+			bur,KX2 = <0x0>;
+			bur,KY0 = <0x0>;
+			bur,KY1 = <0x0>;
+			bur,KY2 = <0x0>;
+		};
+	};
+};
+
+&dcan0 {
+	status = "okay";
+};
+
+&dcan1 {
+	status = "okay";
+};
+
+&sham {
+	status = "disabled";
+};
+
+&aes {
+	status = "disabled";
+};
+
+&rng {
+	status = "disabled";
+};

+ 108 - 0
arch/arm/dts/k3-am65-main.dtsi

@@ -5,6 +5,9 @@
  * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/
  */
 
+#include <dt-bindings/phy/phy-am654-serdes.h>
+#include <dt-bindings/phy/phy.h>
+
 &cbass_main {
 	gic500: interrupt-controller@1800000 {
 		compatible = "arm,gic-v3";
@@ -143,4 +146,109 @@
 		clocks = <&k3_clks 113 1>;
 		power-domains = <&k3_pds 113 TI_SCI_PD_EXCLUSIVE>;
 	};
+
+	scm_conf: scm_conf@100000 {
+		compatible = "syscon", "simple-mfd";
+		reg = <0 0x00100000 0 0x1c000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x0 0x0 0x00100000 0x1c000>;
+
+		serdes_mux: mux-controller {
+			compatible = "mmio-mux";
+			#mux-control-cells = <1>;
+			mux-reg-masks = <0x4080 0x3>, /* SERDES0 lane select */
+					<0x4090 0x3>; /* SERDES1 lane select */
+		};
+
+		pcie0_mode: pcie-mode@4060 {
+			compatible = "syscon";
+			reg = <0x00004060 0x4>;
+		};
+
+		pcie1_mode: pcie-mode@4070 {
+			compatible = "syscon";
+			reg = <0x00004070 0x4>;
+		};
+
+		serdes0_clk: serdes_clk@4080 {
+			compatible = "syscon";
+			reg = <0x00004080 0x4>;
+		};
+
+		serdes1_clk: serdes_clk@4090 {
+			compatible = "syscon";
+			reg = <0x00004090 0x4>;
+		};
+
+		pcie_devid: pcie-devid@210 {
+			compatible = "syscon";
+			reg = <0x00000210 0x4>;
+		};
+	};
+
+	serdes0: serdes@900000 {
+		compatible = "ti,phy-am654-serdes";
+		reg = <0x0 0x900000 0x0 0x2000>;
+		reg-names = "serdes";
+		#phy-cells = <2>;
+		power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 153 4>, <&k3_clks 153 1>, <&serdes1 AM654_SERDES_LO_REFCLK>;
+		clock-output-names = "serdes0_cmu_refclk", "serdes0_lo_refclk", "serdes0_ro_refclk";
+		assigned-clocks = <&k3_clks 153 4>, <&serdes0 AM654_SERDES_CMU_REFCLK>;
+		assigned-clock-parents = <&k3_clks 153 8>, <&k3_clks 153 4>;
+		ti,serdes-clk = <&serdes0_clk>;
+		mux-controls = <&serdes_mux 0>;
+		#clock-cells = <1>;
+	};
+
+	serdes1: serdes@910000 {
+		compatible = "ti,phy-am654-serdes";
+		reg = <0x0 0x910000 0x0 0x2000>;
+		reg-names = "serdes";
+		#phy-cells = <2>;
+		power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&serdes0 AM654_SERDES_RO_REFCLK>, <&k3_clks 154 1>, <&k3_clks 154 5>;
+		clock-output-names = "serdes1_cmu_refclk", "serdes1_lo_refclk", "serdes1_ro_refclk";
+		assigned-clocks = <&k3_clks 154 5>, <&serdes1 AM654_SERDES_CMU_REFCLK>;
+		assigned-clock-parents = <&k3_clks 154 9>, <&k3_clks 154 5>;
+		ti,serdes-clk = <&serdes1_clk>;
+		mux-controls = <&serdes_mux 1>;
+		#clock-cells = <1>;
+	};
+
+	pcie0_rc: pcie@5500000 {
+		compatible = "ti,am654-pcie-rc";
+		reg =  <0x0 0x5500000 0x0 0x1000>, <0x0 0x5501000 0x0 0x1000>, <0x0 0x10000000 0x0 0x2000>, <0x0 0x5506000 0x0 0x1000>;
+		reg-names = "app", "dbics", "config", "atu";
+		power-domains = <&k3_pds 120 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		ranges = <0x81000000 0 0          0x0   0x10020000 0 0x00010000
+			  0x82000000 0 0x10030000 0x0   0x10030000 0 0x07FD0000>;
+		ti,syscon-pcie-id = <&pcie_devid>;
+		ti,syscon-pcie-mode = <&pcie0_mode>;
+		bus-range = <0x0 0xff>;
+		status = "disabled";
+		device_type = "pci";
+		num-lanes = <1>;
+		num-ob-windows = <16>;
+		num-viewport = <16>;
+		max-link-speed = <3>;
+		interrupts = <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie0_intc 0>, /* INT A */
+				<0 0 0 2 &pcie0_intc 0>, /* INT B */
+				<0 0 0 3 &pcie0_intc 0>, /* INT C */
+				<0 0 0 4 &pcie0_intc 0>; /* INT D */
+		msi-map = <0x0 &gic_its 0x0 0x10000>;
+
+		pcie0_intc: legacy-interrupt-controller@1 {
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>;
+		};
+	};
 };

+ 1 - 0
arch/arm/dts/k3-am65.dtsi

@@ -69,6 +69,7 @@
 			 <0x00 0x00900000 0x00 0x00900000 0x00 0x00012000>, /* serdes */
 			 <0x00 0x01000000 0x00 0x01000000 0x00 0x0af02400>, /* Most peripherals */
 			 <0x00 0x30800000 0x00 0x30800000 0x00 0x0bc00000>, /* MAIN NAVSS */
+			 <0x00 0x10000000 0x00 0x10000000 0x00 0x10000000>, /* PCIe DAT */
 			 /* MCUSS Range */
 			 <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>,
 			 <0x00 0x40200000 0x00 0x40200000 0x00 0x00900100>,

+ 5 - 0
arch/arm/include/asm/ti-common/omap_wdt.h

@@ -56,4 +56,9 @@ struct wd_timer {
 	unsigned int wdt_unfr;	/* offset 0x100 */
 };
 
+struct omap3_wdt_priv {
+	struct wd_timer *regs;
+	unsigned int wdt_trgr_pattern;
+};
+
 #endif /* __OMAP_WDT_H__ */

+ 16 - 5
arch/arm/mach-k3/sysfw-loader.c

@@ -251,10 +251,21 @@ void k3_sysfw_loader(void (*config_pm_done_callback)(void))
 	if (config_pm_done_callback)
 		config_pm_done_callback();
 
-	/* Output System Firmware version info */
-	printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%.*s')\n",
+	/*
+	 * Output System Firmware version info. Note that since the
+	 * 'firmware_description' field is not guaranteed to be zero-
+	 * terminated we manually add a \0 terminator if needed. Further
+	 * note that we intentionally no longer rely on the extended
+	 * printf() formatter '%.*s' to not having to require a more
+	 * full-featured printf() implementation.
+	 */
+	char fw_desc[sizeof(ti_sci->version.firmware_description) + 1];
+
+	strncpy(fw_desc, ti_sci->version.firmware_description,
+		sizeof(ti_sci->version.firmware_description));
+	fw_desc[sizeof(fw_desc) - 1] = '\0';
+
+	printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')\n",
 	       ti_sci->version.abi_major, ti_sci->version.abi_minor,
-	       ti_sci->version.firmware_revision,
-	       sizeof(ti_sci->version.firmware_description),
-	       ti_sci->version.firmware_description);
+	       ti_sci->version.firmware_revision, fw_desc);
 }

+ 1 - 0
arch/arm/mach-omap2/Kconfig

@@ -176,6 +176,7 @@ source "arch/arm/mach-omap2/omap5/Kconfig"
 source "arch/arm/mach-omap2/am33xx/Kconfig"
 
 source "board/BuR/brxre1/Kconfig"
+source "board/BuR/brsmarc1/Kconfig"
 source "board/BuR/brppt1/Kconfig"
 source "board/siemens/draco/Kconfig"
 source "board/siemens/pxm2/Kconfig"

+ 4 - 0
arch/arm/mach-omap2/am33xx/Kconfig

@@ -121,6 +121,10 @@ config TARGET_BRXRE1
 	bool "Support BRXRE1"
 	select BOARD_LATE_INIT
 
+config TARGET_BRSMARC1
+	bool "Support BRSMARC1"
+	select BOARD_LATE_INIT
+
 config TARGET_BRPPT1
 	bool "Support BRPPT1"
 	select BOARD_LATE_INIT

+ 1 - 1
arch/arm/mach-omap2/boot-common.c

@@ -207,7 +207,7 @@ void spl_board_init(void)
 #if defined(CONFIG_AM33XX) && defined(CONFIG_SPL_MUSB_NEW_SUPPORT)
 	arch_misc_init();
 #endif
-#if defined(CONFIG_HW_WATCHDOG)
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
 	hw_watchdog_init();
 #endif
 #ifdef CONFIG_AM33XX

+ 15 - 0
board/BuR/brsmarc1/Kconfig

@@ -0,0 +1,15 @@
+if TARGET_BRSMARC1
+
+config SYS_BOARD
+	default "brsmarc1"
+
+config SYS_VENDOR
+	default "BuR"
+
+config SYS_SOC
+	default "am33xx"
+
+config SYS_CONFIG_NAME
+	default "brsmarc1"
+
+endif

+ 6 - 0
board/BuR/brsmarc1/MAINTAINERS

@@ -0,0 +1,6 @@
+BRSMARC1 BOARD
+M:	Hannes Schmelzer <hannes.schmelzer@br-automation.com>
+S:	Maintained
+F:	board/BuR/brsmarc1/
+F:	include/configs/brsmarc1.h
+F:	configs/brsmarc1_defconfig

+ 10 - 0
board/BuR/brsmarc1/Makefile

@@ -0,0 +1,10 @@
+# SPDX-License-Identifier:	GPL-2.0+
+#
+# Copyright (C) 2019 Hannes Schmelzer <oe5hpm@oevsv.at> -
+# B&R Industrial Automation GmbH - http://www.br-automation.com/
+#
+
+obj-$(CONFIG_SPL_BUILD) += mux.o
+obj-y	+= ../common/br_resetc.o
+obj-y	+= ../common/common.o
+obj-y	+= board.o

+ 168 - 0
board/BuR/brsmarc1/board.c

@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * board.c
+ *
+ * Board functions for B&R BRSMARC1 Board
+ *
+ * Copyright (C) 2017 Hannes Schmelzer <oe5hpm@oevsv.at>
+ * B&R Industrial Automation GmbH - http://www.br-automation.com
+ *
+ */
+#include <common.h>
+#include <errno.h>
+#include <spl.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/omap.h>
+#include <asm/arch/ddr_defs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/mem.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/emif.h>
+#include <power/tps65217.h>
+#include "../common/bur_common.h"
+#include "../common/br_resetc.h"
+
+/* -------------------------------------------------------------------------*/
+/* -- defines for used GPIO Hardware -- */
+#define PER_RESET		(2 * 32 + 0)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_SPL_BUILD)
+static const struct ddr_data ddr3_data = {
+	.datardsratio0 = MT41K256M16HA125E_RD_DQS,
+	.datawdsratio0 = MT41K256M16HA125E_WR_DQS,
+	.datafwsratio0 = MT41K256M16HA125E_PHY_FIFO_WE,
+	.datawrsratio0 = MT41K256M16HA125E_PHY_WR_DATA,
+};
+
+static const struct cmd_control ddr3_cmd_ctrl_data = {
+	.cmd0csratio = MT41K256M16HA125E_RATIO,
+	.cmd0iclkout = MT41K256M16HA125E_INVERT_CLKOUT,
+
+	.cmd1csratio = MT41K256M16HA125E_RATIO,
+	.cmd1iclkout = MT41K256M16HA125E_INVERT_CLKOUT,
+
+	.cmd2csratio = MT41K256M16HA125E_RATIO,
+	.cmd2iclkout = MT41K256M16HA125E_INVERT_CLKOUT,
+};
+
+static struct emif_regs ddr3_emif_reg_data = {
+	.sdram_config = MT41K256M16HA125E_EMIF_SDCFG,
+	.ref_ctrl = MT41K256M16HA125E_EMIF_SDREF,
+	.sdram_tim1 = MT41K256M16HA125E_EMIF_TIM1,
+	.sdram_tim2 = MT41K256M16HA125E_EMIF_TIM2,
+	.sdram_tim3 = MT41K256M16HA125E_EMIF_TIM3,
+	.zq_config = MT41K256M16HA125E_ZQ_CFG,
+	.emif_ddr_phy_ctlr_1 = MT41K256M16HA125E_EMIF_READ_LATENCY,
+};
+
+static const struct ctrl_ioregs ddr3_ioregs = {
+	.cm0ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
+	.cm1ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
+	.cm2ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
+	.dt0ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
+	.dt1ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
+};
+
+#define OSC	(V_OSCK / 1000000)
+const struct dpll_params dpll_ddr3 = { 400, OSC - 1, 1, -1, -1, -1, -1};
+
+void am33xx_spl_board_init(void)
+{
+	struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER;
+	struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP;
+
+	int rc;
+	/*
+	 * enable additional clocks of modules which are accessed later from
+	 * VxWorks OS
+	 */
+	u32 *const clk_domains[] = { 0 };
+	u32 *const clk_modules_specific[] = {
+		&cmwkup->wkup_adctscctrl,
+		&cmper->spi1clkctrl,
+		&cmper->dcan0clkctrl,
+		&cmper->dcan1clkctrl,
+		&cmper->timer4clkctrl,
+		&cmper->timer5clkctrl,
+		&cmper->lcdclkctrl,
+		&cmper->lcdcclkstctrl,
+		0
+	};
+	do_enable_clocks(clk_domains, clk_modules_specific, 1);
+
+	/* setup I2C */
+	enable_i2c_pin_mux();
+
+	/* peripheral reset */
+	rc = gpio_request(PER_RESET, "PER_RESET");
+	if (rc != 0)
+		printf("cannot request PER_RESET GPIO!\n");
+
+	rc = gpio_direction_output(PER_RESET, 0);
+	if (rc != 0)
+		printf("cannot set PER_RESET GPIO!\n");
+
+	/* setup pmic */
+	pmicsetup(0, 0);
+}
+
+const struct dpll_params *get_dpll_ddr_params(void)
+{
+	return &dpll_ddr3;
+}
+
+void sdram_init(void)
+{
+	config_ddr(400, &ddr3_ioregs,
+		   &ddr3_data,
+		   &ddr3_cmd_ctrl_data,
+		   &ddr3_emif_reg_data, 0);
+}
+#endif /* CONFIG_SPL_BUILD */
+#if !defined(CONFIG_SPL_BUILD)
+
+/* decision if backlight is switched on or not on powerup */
+int board_backlightstate(void)
+{
+	u8 bklmask, rstcause;
+	int rc = 0;
+
+	rc |= br_resetc_regget(RSTCTRL_SCRATCHREG1, &bklmask);
+	rc |= br_resetc_regget(RSTCTRL_ERSTCAUSE, &rstcause);
+
+	if (rc != 0) {
+		printf("%s: read rstctrl failed!\n", __func__);
+		return 1;
+	}
+
+	if ((rstcause & bklmask) != 0)
+		return 0;
+
+	return 1;
+}
+
+/* Basic board specific setup. run quite after relocation */
+int board_init(void)
+{
+	if (power_tps65217_init(0))
+		printf("WARN: cannot setup PMIC 0x24 @ bus #0, not found!.\n");
+
+	return 0;
+}
+
+#if defined(CONFIG_BOARD_LATE_INIT)
+
+int board_late_init(void)
+{
+	br_resetc_bmode();
+
+	return 0;
+}
+
+#endif /* CONFIG_BOARD_LATE_INIT */
+#endif /* !CONFIG_SPL_BUILD */

+ 33 - 0
board/BuR/brsmarc1/config.mk

@@ -0,0 +1,33 @@
+# SPDX-License-Identifier:	GPL-2.0+
+#
+# Copyright (C) 2019 Hannes Schmelzer <oe5hpm@oevsv.at> -
+# B&R Industrial Automation GmbH - http://www.br-automation.com
+#
+
+hw-platform-y :=$(shell echo $(CONFIG_DEFAULT_DEVICE_TREE) | sed -e 's/am335x-//')
+
+payload_off :=$(shell printf "%d" $(CONFIG_SYS_SPI_U_BOOT_OFFS))
+
+quiet_cmd_prodbin = PRODBIN $@ $(payload_off)
+cmd_prodbin =								\
+	dd if=/dev/zero ibs=1M count=2 2>/dev/null | tr "\000" "\377" >$@ && \
+	dd conv=notrunc bs=1 if=MLO.byteswap of=$@ seek=0 2>/dev/null && \
+	dd bs=1 if=u-boot-dtb.img of=$@ seek=$(payload_off) 2>/dev/null
+
+quiet_cmd_prodzip = SAPZIP  $@
+cmd_prodzip =					\
+	test -d misc && rm -r misc;		\
+	mkdir misc &&				\
+	cp MLO.byteswap misc/ &&		\
+	cp spl/u-boot-spl.bin misc/ &&		\
+	cp u-boot-dtb.img misc/ &&		\
+	zip -9 -r $@ misc/* >/dev/null $<
+
+ALL-y += $(hw-platform-y)_prog.bin
+ALL-y += $(hw-platform-y)_prod.zip
+
+$(hw-platform-y)_prog.bin: u-boot-dtb.img spl/u-boot-spl.bin
+	$(call if_changed,prodbin)
+
+$(hw-platform-y)_prod.zip: $(hw-platform-y)_prog.bin
+	$(call if_changed,prodzip)

+ 266 - 0
board/BuR/brsmarc1/mux.c

@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * mux.c
+ *
+ * Pinmux Setting for B&R BRSMARC1 Board (HW-Rev. 1)
+ *
+ * Copyright (C) 2017 Hannes Schmelzer <hannes.schmelzer@br-automation.com>
+ * B&R Industrial Automation GmbH - http://www.br-automation.com
+ *
+ */
+
+#include <common.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/mux.h>
+#include <asm/io.h>
+#include <i2c.h>
+
+static struct module_pin_mux spi0_pin_mux[] = {
+	/* SPI0_SCLK */
+	{OFFSET(spi0_sclk),	MODE(0) | PULLUDEN | RXACTIVE},
+	/* SPI0_D0 */
+	{OFFSET(spi0_d0),	MODE(0) | PULLUDEN | RXACTIVE},
+	/* SPI0_D1 */
+	{OFFSET(spi0_d1),	MODE(0) | PULLUDEN | RXACTIVE},
+	/* SPI0_CS0 */
+	{OFFSET(spi0_cs0),	MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE},
+	/* SPI0_CS1 */
+	{OFFSET(spi0_cs1),	MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE},
+	{-1},
+};
+
+static struct module_pin_mux spi1_pin_mux[] = {
+	/* SPI1_SCLK */
+	{OFFSET(mcasp0_aclkx),	MODE(3) | PULLUDEN | RXACTIVE},
+	/* SPI1_D0 */
+	{OFFSET(mcasp0_fsx),	MODE(3) | PULLUDEN | RXACTIVE},
+	/* SPI1_D1 */
+	{OFFSET(mcasp0_axr0),	MODE(3) | PULLUDEN | RXACTIVE},
+	/* SPI1_CS0 */
+	{OFFSET(mcasp0_ahclkr),	MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE},
+	/* SPI1_CS1 */
+	{OFFSET(xdma_event_intr0), MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE},
+	{-1},
+};
+
+static struct module_pin_mux dcan0_pin_mux[] = {
+	/* DCAN0 TX */
+	{OFFSET(uart1_ctsn),	MODE(2) | PULLUDEN | PULLUP_EN},
+	/* DCAN0 RX */
+	{OFFSET(uart1_rtsn),	MODE(2) | RXACTIVE},
+	{-1},
+};
+
+static struct module_pin_mux dcan1_pin_mux[] = {
+	/* DCAN1 TX */
+	{OFFSET(uart0_ctsn),	MODE(2) | PULLUDEN | PULLUP_EN},
+	/* DCAN1 RX */
+	{OFFSET(uart0_rtsn),	MODE(2) | RXACTIVE},
+	{-1},
+};
+
+static struct module_pin_mux gpios[] = {
+	/* GPIO0_7 - LVDS_EN */
+	{OFFSET(ecap0_in_pwm0_out), (MODE(7) | PULLUDDIS | PULLDOWN_EN)},
+	/* GPIO0_20 - BKLT_PWM (timer7) */
+	{OFFSET(xdma_event_intr1), (MODE(4) | PULLUDDIS | PULLDOWN_EN)},
+	/* GPIO2_4 - DISON */
+	{OFFSET(gpmc_wen), (MODE(7) | PULLUDDIS | PULLDOWN_EN)},
+	/* GPIO1_24 - RGB_EN */
+	{OFFSET(gpmc_a8), (MODE(7) | PULLUDDIS | PULLDOWN_EN)},
+	/* GPIO1_28 - nPD */
+	{OFFSET(gpmc_be1n), (MODE(7) | PULLUDEN | PULLUP_EN)},
+	/* GPIO2_5 - Watchdog */
+	{OFFSET(gpmc_be0n_cle), (MODE(7) | PULLUDDIS | PULLDOWN_EN)},
+	/* GPIO2_0 - ResetOut */
+	{OFFSET(gpmc_csn3), (MODE(7) | PULLUDEN | PULLUP_EN)},
+	/* GPIO2_2 - BKLT_EN */
+	{OFFSET(gpmc_advn_ale), (MODE(7) | PULLUDDIS | PULLDOWN_EN)},
+	/* GPIO1_17 - GPIO0 */
+	{OFFSET(gpmc_a1), (MODE(7) | PULLUDDIS | RXACTIVE)},
+	/* GPIO1_18 - GPIO1 */
+	{OFFSET(gpmc_a2), (MODE(7) | PULLUDDIS | RXACTIVE)},
+	/* GPIO1_19 - GPIO2 */
+	{OFFSET(gpmc_a3), (MODE(7) | PULLUDDIS | RXACTIVE)},
+	/* GPIO1_22 - GPIO3 */
+	{OFFSET(gpmc_a6), (MODE(7) | PULLUDDIS | RXACTIVE)},
+	/* GPIO1_23 - GPIO4 */
+	{OFFSET(gpmc_a7), (MODE(7) | PULLUDDIS | RXACTIVE)},
+	/* GPIO1_25 - GPIO5 */
+	{OFFSET(gpmc_a9), (MODE(7) | PULLUDDIS | RXACTIVE)},
+	/* GPIO3_7 - GPIO6 */
+	{OFFSET(emu0), (MODE(7) | PULLUDDIS | RXACTIVE)},
+	/* GPIO3_8 - GPIO7 */
+	{OFFSET(emu1), (MODE(7) | PULLUDDIS | RXACTIVE)},
+	/* GPIO3_18 - GPIO8 */
+	{OFFSET(mcasp0_aclkr), (MODE(7) | PULLUDDIS | RXACTIVE)},
+	/* GPIO3_19 - GPIO9 */
+	{OFFSET(mcasp0_fsr), (MODE(7) | PULLUDDIS | RXACTIVE)},
+	/* GPIO3_20 - GPIO10 */
+	{OFFSET(mcasp0_axr1), (MODE(7) | PULLUDDIS | RXACTIVE)},
+	/* GPIO3_21 - GPIO11 */
+	{OFFSET(mcasp0_ahclkx), (MODE(7) | PULLUDDIS | RXACTIVE)},
+	/* GPIO2_28 - DRAM-strapping */
+	{OFFSET(mmc0_dat1), (MODE(7) | PULLUDEN | PULLUP_EN)},
+	/* GPIO2_4 - not routed (Pin U6) */
+	{OFFSET(gpmc_wen), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
+	/* GPIO2_5 - not routed (Pin T6) */
+	{OFFSET(gpmc_be0n_cle), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
+	/* GPIO2_28 - not routed (Pin G15) */
+	{OFFSET(mmc0_dat1), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
+	/* GPIO3_18 - not routed (Pin B12) */
+	{OFFSET(mcasp0_aclkr), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
+	{-1},
+};
+
+static struct module_pin_mux uart0_pin_mux[] = {
+	/* UART0_RXD */
+	{OFFSET(uart0_rxd), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)},
+	/* UART0_TXD */
+	{OFFSET(uart0_txd), (MODE(0) | PULLUDEN)},
+	{-1},
+};
+
+static struct module_pin_mux uart234_pin_mux[] = {
+	/* UART2_RXD */
+	{OFFSET(mii1_txclk), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)},
+	/* UART2_TXD */
+	{OFFSET(mii1_rxclk), (MODE(1) | PULLUDEN)},
+
+	/* UART3_RXD */
+	{OFFSET(mii1_rxd3), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)},
+	/* UART3_TXD */
+	{OFFSET(mmc0_dat0), (MODE(3) | PULLUDEN)},
+	/* UART3_RTS */
+	{OFFSET(mmc0_cmd), (MODE(2) | PULLUDEN)},
+	/* UART3_CTS */
+	{OFFSET(mmc0_clk), (MODE(2) | PULLUDEN | PULLUP_EN | RXACTIVE)},
+
+	/* UART4_RXD */
+	{OFFSET(mii1_txd3), (MODE(3) | PULLUDEN | PULLUP_EN | RXACTIVE)},
+	/* UART4_TXD */
+	{OFFSET(mii1_txd2), (MODE(3) | PULLUDEN)},
+	/* UART4_RTS */
+	{OFFSET(mmc0_dat2), (MODE(3) | PULLUDEN)},
+	/* UART4_CTS */
+	{OFFSET(mmc0_dat3), (MODE(3) | PULLUDEN | PULLUP_EN | RXACTIVE)},
+
+	{-1},
+};
+
+static struct module_pin_mux i2c_pin_mux[] = {
+	/* I2C0_DATA */
+	{OFFSET(i2c0_sda), (MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL)},
+	/* I2C0_SCLK */
+	{OFFSET(i2c0_scl), (MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL)},
+	/* I2C1_DATA */
+	{OFFSET(uart1_rxd), (MODE(3) | RXACTIVE | PULLUDEN | SLEWCTRL)},
+	/* I2C1_SCLK */
+	{OFFSET(uart1_txd), (MODE(3) | RXACTIVE | PULLUDEN | SLEWCTRL)},
+	{-1},
+};
+
+static struct module_pin_mux eth_pin_mux[] = {
+	/* ETH1 */
+	{OFFSET(rmii1_refclk), MODE(0) | RXACTIVE},	/* ETH1_REFCLK */
+	{OFFSET(mii1_crs), MODE(1) | RXACTIVE},		/* RMII1_CRSDV */
+	{OFFSET(mii1_rxerr), MODE(1) | RXACTIVE},	/* RMII1_RXER */
+	{OFFSET(mii1_txen), MODE(1)},			/* RMII1_TXEN */
+	{OFFSET(mii1_rxd0), MODE(1) | RXACTIVE},	/* RMII1_RXD0 */
+	{OFFSET(mii1_rxd1), MODE(1) | RXACTIVE},	/* RMII1_RXD1 */
+	{OFFSET(mii1_txd0), MODE(1)},			/* RMII1_TXD0 */
+	{OFFSET(mii1_txd1), MODE(1)},			/* RMII1_TXD1 */
+
+	/* ETH2 */
+	{OFFSET(mii1_col), MODE(1) | RXACTIVE},		/* ETH2_REFCLK */
+	{OFFSET(gpmc_wait0), MODE(3) | RXACTIVE},	/* RMII2_CRSDV */
+	{OFFSET(gpmc_wpn), MODE(3) | RXACTIVE},		/* RMII2_RXER */
+	{OFFSET(gpmc_a0), MODE(3)},			/* RMII2_TXEN */
+	{OFFSET(gpmc_a11), MODE(3) | RXACTIVE},		/* RMII2_RXD0 */
+	{OFFSET(gpmc_a10), MODE(3) | RXACTIVE},		/* RMII2_RXD1 */
+	{OFFSET(gpmc_a5), MODE(3)},			/* RMII2_TXD0 */
+	{OFFSET(gpmc_a4), MODE(3)},			/* RMII2_TXD1 */
+
+	/* gpio2_19, gpio 3_4, not connected on board */
+	{OFFSET(mii1_rxd2), MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE},
+	{OFFSET(mii1_rxdv), MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE},
+
+	/* ETH Management */
+	{OFFSET(mdio_data), MODE(0) | RXACTIVE | PULLUP_EN},	/* MDIO_DATA */
+	{OFFSET(mdio_clk), MODE(0) | PULLUP_EN},		/* MDIO_CLK */
+
+	{-1},
+};
+
+static struct module_pin_mux mmc1_pin_mux[] = {
+	{OFFSET(gpmc_ad7), (MODE(1) | RXACTIVE | PULLUP_EN)},	/* MMC1_DAT7 */
+	{OFFSET(gpmc_ad6), (MODE(1) | RXACTIVE | PULLUP_EN)},	/* MMC1_DAT6 */
+	{OFFSET(gpmc_ad5), (MODE(1) | RXACTIVE | PULLUP_EN)},	/* MMC1_DAT5 */
+	{OFFSET(gpmc_ad4), (MODE(1) | RXACTIVE | PULLUP_EN)},	/* MMC1_DAT4 */
+	{OFFSET(gpmc_ad3), (MODE(1) | RXACTIVE | PULLUP_EN)},	/* MMC1_DAT3 */
+	{OFFSET(gpmc_ad2), (MODE(1) | RXACTIVE | PULLUP_EN)},	/* MMC1_DAT2 */
+	{OFFSET(gpmc_ad1), (MODE(1) | RXACTIVE | PULLUP_EN)},	/* MMC1_DAT1 */
+	{OFFSET(gpmc_ad0), (MODE(1) | RXACTIVE | PULLUP_EN)},	/* MMC1_DAT0 */
+	{OFFSET(gpmc_csn1), (MODE(2) | RXACTIVE | PULLUP_EN)},	/* MMC1_CLK */
+	{OFFSET(gpmc_csn2), (MODE(2) | RXACTIVE | PULLUP_EN)},	/* MMC1_CMD */
+	{-1},
+};
+
+static struct module_pin_mux lcd_pin_mux[] = {
+	{OFFSET(lcd_data0), (MODE(0) | PULLUDDIS)},	/* LCD-Data(0) */
+	{OFFSET(lcd_data1), (MODE(0) | PULLUDDIS)},	/* LCD-Data(1) */
+	{OFFSET(lcd_data2), (MODE(0) | PULLUDDIS)},	/* LCD-Data(2) */
+	{OFFSET(lcd_data3), (MODE(0) | PULLUDDIS)},	/* LCD-Data(3) */
+	{OFFSET(lcd_data4), (MODE(0) | PULLUDDIS)},	/* LCD-Data(4) */
+	{OFFSET(lcd_data5), (MODE(0) | PULLUDDIS)},	/* LCD-Data(5) */
+	{OFFSET(lcd_data6), (MODE(0) | PULLUDDIS)},	/* LCD-Data(6) */
+	{OFFSET(lcd_data7), (MODE(0) | PULLUDDIS)},	/* LCD-Data(7) */
+	{OFFSET(lcd_data8), (MODE(0) | PULLUDDIS)},	/* LCD-Data(8) */
+	{OFFSET(lcd_data9), (MODE(0) | PULLUDDIS)},	/* LCD-Data(9) */
+	{OFFSET(lcd_data10), (MODE(0) | PULLUDDIS)},	/* LCD-Data(10) */
+	{OFFSET(lcd_data11), (MODE(0) | PULLUDDIS)},	/* LCD-Data(11) */
+	{OFFSET(lcd_data12), (MODE(0) | PULLUDDIS)},	/* LCD-Data(12) */
+	{OFFSET(lcd_data13), (MODE(0) | PULLUDDIS)},	/* LCD-Data(13) */
+	{OFFSET(lcd_data14), (MODE(0) | PULLUDDIS)},	/* LCD-Data(14) */
+	{OFFSET(lcd_data15), (MODE(0) | PULLUDDIS)},	/* LCD-Data(15) */
+
+	{OFFSET(gpmc_ad8), (MODE(1) | PULLUDDIS)},	/* LCD-Data(16) */
+	{OFFSET(gpmc_ad9), (MODE(1) | PULLUDDIS)},	/* LCD-Data(17) */
+	{OFFSET(gpmc_ad10), (MODE(1) | PULLUDDIS)},	/* LCD-Data(18) */
+	{OFFSET(gpmc_ad11), (MODE(1) | PULLUDDIS)},	/* LCD-Data(19) */
+	{OFFSET(gpmc_ad12), (MODE(1) | PULLUDDIS)},	/* LCD-Data(20) */
+	{OFFSET(gpmc_ad13), (MODE(1) | PULLUDDIS)},	/* LCD-Data(21) */
+	{OFFSET(gpmc_ad14), (MODE(1) | PULLUDDIS)},	/* LCD-Data(22) */
+	{OFFSET(gpmc_ad15), (MODE(1) | PULLUDDIS)},	/* LCD-Data(23) */
+
+	{OFFSET(lcd_vsync), (MODE(0) | PULLUDDIS)},	/* LCD-VSync */
+	{OFFSET(lcd_hsync), (MODE(0) | PULLUDDIS)},	/* LCD-HSync */
+	{OFFSET(lcd_ac_bias_en), (MODE(0) | PULLUDDIS)},/* LCD-DE */
+	{OFFSET(lcd_pclk), (MODE(0) | PULLUDDIS)},	/* LCD-CLK */
+
+	{-1},
+};
+
+void enable_uart0_pin_mux(void)
+{
+	configure_module_pin_mux(uart0_pin_mux);
+}
+
+void enable_i2c_pin_mux(void)
+{
+	configure_module_pin_mux(i2c_pin_mux);
+}
+
+void enable_board_pin_mux(void)
+{
+	configure_module_pin_mux(eth_pin_mux);
+	configure_module_pin_mux(spi0_pin_mux);
+	configure_module_pin_mux(spi1_pin_mux);
+	configure_module_pin_mux(dcan0_pin_mux);
+	configure_module_pin_mux(dcan1_pin_mux);
+	configure_module_pin_mux(uart234_pin_mux);
+	configure_module_pin_mux(mmc1_pin_mux);
+	configure_module_pin_mux(lcd_pin_mux);
+	configure_module_pin_mux(gpios);
+}

+ 2 - 1
board/davinci/da8xxevm/da850evm.c

@@ -234,7 +234,8 @@ const struct pinmux_resource pinmuxes[] = {
 	PINMUX_ITEM(emifa_pins_cs3),
 	PINMUX_ITEM(emifa_pins_cs4),
 	PINMUX_ITEM(emifa_pins_nand),
-#elif defined(CONFIG_USE_NOR)
+#endif
+#ifdef CONFIG_USE_NOR
 	PINMUX_ITEM(emifa_pins_cs2),
 	PINMUX_ITEM(emifa_pins_nor),
 #endif

+ 26 - 0
board/overo/common.c

@@ -17,6 +17,7 @@
 #include <asm/arch/mux.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/gpio.h>
+#include <asm/omap_mmc.h>
 #include <asm/mach-types.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -38,6 +39,31 @@ int board_init(void)
 	return 0;
 }
 
+#if defined(CONFIG_MMC)
+int board_mmc_init(bd_t *bis)
+{
+	return omap_mmc_init(0, 0, 0, -1, -1);
+}
+#endif
+
+#if defined(CONFIG_MMC)
+void board_mmc_power_init(void)
+{
+	twl4030_power_mmc_init(0);
+}
+#endif
+
+#if defined(CONFIG_SPL_OS_BOOT)
+int spl_start_uboot(void)
+{
+	/* break into full u-boot on 'c' */
+	if (serial_tstc() && serial_getc() == 'c')
+		return 1;
+
+	return 0;
+}
+#endif /* CONFIG_SPL_OS_BOOT */
+
 #define MUX_OVERO() \
  /*SDRC*/\
 	MUX_VAL(CP(SDRC_D0),		(IEN  | PTD | DIS | M0)) /*SDRC_D0*/\

+ 0 - 14
board/overo/overo.c

@@ -377,20 +377,6 @@ int board_eth_init(bd_t *bis)
 }
 #endif
 
-#if defined(CONFIG_MMC)
-int board_mmc_init(bd_t *bis)
-{
-	return omap_mmc_init(0, 0, 0, -1, -1);
-}
-#endif
-
-#if defined(CONFIG_MMC)
-void board_mmc_power_init(void)
-{
-	twl4030_power_mmc_init(0);
-}
-#endif
-
 #if defined(CONFIG_USB_EHCI_HCD)
 static struct omap_usbhs_board_data usbhs_bdata = {
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,

+ 107 - 17
board/siemens/common/factoryset.c

@@ -9,6 +9,8 @@
 
 #include <common.h>
 #include <env.h>
+#include <dm.h>
+#include <env_internal.h>
 #include <i2c.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
@@ -143,16 +145,39 @@ int factoryset_read_eeprom(int i2c_addr)
 	int i, pages = 0, size = 0;
 	unsigned char eeprom_buf[0x3c00], hdr[4], buf[MAX_STRING_LENGTH];
 	unsigned char *cp, *cp1;
+#if CONFIG_IS_ENABLED(DM_I2C)
+	struct udevice *bus, *dev;
+	int ret;
+#endif
 
 #if defined(CONFIG_DFU_OVER_USB)
 	factory_dat.usb_vendor_id = CONFIG_USB_GADGET_VENDOR_NUM;
 	factory_dat.usb_product_id = CONFIG_USB_GADGET_PRODUCT_NUM;
 #endif
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+	ret = uclass_get_device_by_seq(UCLASS_I2C, EEPROM_I2C_BUS, &bus);
+	if (ret)
+		goto err;
+
+	ret = dm_i2c_probe(bus, i2c_addr, 0, &dev);
+	if (ret)
+		goto err;
+
+	ret = i2c_set_chip_offset_len(dev, 2);
+	if (ret)
+		goto err;
+
+	ret = dm_i2c_read(dev, EEPROM_FATORYSET_OFFSET, hdr, sizeof(hdr));
+	if (ret)
+		goto err;
+#else
 	if (i2c_probe(i2c_addr))
 		goto err;
 
 	if (i2c_read(i2c_addr, EEPROM_FATORYSET_OFFSET, 2, hdr, sizeof(hdr)))
 		goto err;
+#endif
 
 	if ((hdr[0] != 0x99) || (hdr[1] != 0x80)) {
 		printf("FactorySet is not right in eeprom.\n");
@@ -173,16 +198,33 @@ int factoryset_read_eeprom(int i2c_addr)
 	 * data after every time we got a record from eeprom
 	 */
 	debug("Read eeprom page :\n");
-	for (i = 0; i < pages; i++)
+	for (i = 0; i < pages; i++) {
+#if CONFIG_IS_ENABLED(DM_I2C)
+		ret = dm_i2c_read(dev, (OFF_PG + i) * EEPR_PG_SZ,
+				  eeprom_buf + (i * EEPR_PG_SZ), EEPR_PG_SZ);
+		if (ret)
+			goto err;
+#else
 		if (i2c_read(i2c_addr, (OFF_PG + i) * EEPR_PG_SZ, 2,
 			     eeprom_buf + (i * EEPR_PG_SZ), EEPR_PG_SZ))
 			goto err;
+#endif
+	}
 
-	if (size % EEPR_PG_SZ)
+	if (size % EEPR_PG_SZ) {
+#if CONFIG_IS_ENABLED(DM_I2C)
+		ret = dm_i2c_read(dev, (OFF_PG + pages) * EEPR_PG_SZ,
+				  eeprom_buf + (pages * EEPR_PG_SZ),
+				  size % EEPR_PG_SZ);
+		if (ret)
+			goto err;
+#else
 		if (i2c_read(i2c_addr, (OFF_PG + pages) * EEPR_PG_SZ, 2,
 			     eeprom_buf + (pages * EEPR_PG_SZ),
 			     (size % EEPR_PG_SZ)))
 			goto err;
+#endif
+	}
 
 	/* we do below just for eeprom align */
 	for (i = 0; i < size; i++)
@@ -202,6 +244,20 @@ int factoryset_read_eeprom(int i2c_addr)
 		cp1 += 3;
 	}
 
+#if CONFIG_IS_ENABLED(TARGET_GIEDI) || CONFIG_IS_ENABLED(TARGET_DENEB)
+	/* get mac address for WLAN */
+	ret = get_factory_record_val(cp, size, (uchar *)"WLAN1", (uchar *)"mac",
+				     buf, MAX_STRING_LENGTH);
+	if (ret > 0) {
+		cp1 = buf;
+		for (i = 0; i < 6; i++) {
+			factory_dat.mac_wlan[i] = simple_strtoul((char *)cp1,
+								 NULL, 16);
+			cp1 += 3;
+		}
+	}
+#endif
+
 #if defined(CONFIG_DFU_OVER_USB)
 	/* read vid and pid for dfu mode */
 	if (0 <= get_factory_record_val(cp, size, (uchar *)"USBD1",
@@ -264,42 +320,76 @@ err:
 	return 1;
 }
 
-static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
+static int get_mac_from_efuse(uint8_t mac[6])
+{
+#ifdef CONFIG_AM33XX
+	struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
+	uint32_t mac_hi, mac_lo;
+
+	mac_lo = readl(&cdev->macid0l);
+	mac_hi = readl(&cdev->macid0h);
+
+	mac[0] = mac_hi & 0xFF;
+	mac[1] = (mac_hi & 0xFF00) >> 8;
+	mac[2] = (mac_hi & 0xFF0000) >> 16;
+	mac[3] = (mac_hi & 0xFF000000) >> 24;
+	mac[4] = mac_lo & 0xFF;
+	mac[5] = (mac_lo & 0xFF00) >> 8;
+#else
+	/* unhandled */
+	memset(mac, 0, 6);
+#endif
+	if (!is_valid_ethaddr(mac)) {
+		puts("Warning: ethaddr not set by FactorySet or E-fuse. ");
+		puts("Set <ethaddr> variable to overcome this.\n");
+		return -1;
+	}
+	return 0;
+}
 
 static int factoryset_mac_env_set(void)
 {
 	uint8_t mac_addr[6];
 
+	/* Set mac from factoryset or try reading E-fuse */
 	debug("FactorySet: Set mac address\n");
 	if (is_valid_ethaddr(factory_dat.mac)) {
 		memcpy(mac_addr, factory_dat.mac, 6);
 	} else {
-		uint32_t mac_hi, mac_lo;
-
 		debug("Warning: FactorySet: <ethaddr> not set. Fallback to E-fuse\n");
-		mac_lo = readl(&cdev->macid0l);
-		mac_hi = readl(&cdev->macid0h);
-
-		mac_addr[0] = mac_hi & 0xFF;
-		mac_addr[1] = (mac_hi & 0xFF00) >> 8;
-		mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
-		mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
-		mac_addr[4] = mac_lo & 0xFF;
-		mac_addr[5] = (mac_lo & 0xFF00) >> 8;
-		if (!is_valid_ethaddr(mac_addr)) {
-			printf("Warning: ethaddr not set by FactorySet or E-fuse. Set <ethaddr> variable to overcome this.\n");
+		if (get_mac_from_efuse(mac_addr) < 0)
 			return -1;
-		}
 	}
 
 	eth_env_set_enetaddr("ethaddr", mac_addr);
+
+#if CONFIG_IS_ENABLED(TARGET_GIEDI) || CONFIG_IS_ENABLED(TARGET_DENEB)
+	eth_env_set_enetaddr("eth1addr", mac_addr);
+
+	/* wlan mac */
+	if (is_valid_ethaddr(factory_dat.mac_wlan))
+		eth_env_set_enetaddr("eth2addr", factory_dat.mac_wlan);
+#endif
 	return 0;
 }
 
+static void factoryset_dtb_env_set(void)
+{
+	/* Set ASN in environment*/
+	if (factory_dat.asn[0] != 0) {
+		env_set("dtb_name", (char *)factory_dat.asn);
+	} else {
+		/* dtb suffix gets added in load script */
+		env_set("dtb_name", "default");
+	}
+}
+
 int factoryset_env_set(void)
 {
 	int ret = 0;
 
+	factoryset_dtb_env_set();
+
 	if (factoryset_mac_env_set() < 0)
 		ret = -1;
 

+ 3 - 0
board/siemens/common/factoryset.h

@@ -11,6 +11,9 @@
 
 struct factorysetcontainer {
 	uchar mac[6];
+#if CONFIG_IS_ENABLED(TARGET_GIEDI) || CONFIG_IS_ENABLED(TARGET_DENEB)
+	uchar mac_wlan[6];
+#endif
 	int usb_vendor_id;
 	int usb_product_id;
 	int pxm50;

+ 3 - 0
configs/am335x_evm_defconfig

@@ -58,6 +58,9 @@ CONFIG_DM_SPI=y
 CONFIG_OMAP3_SPI=y
 CONFIG_TIMER=y
 CONFIG_OMAP_TIMER=y
+CONFIG_WDT=y
+CONFIG_WDT_OMAP3=y
+# CONFIG_SPL_WDT is not set
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB_GADGET=y

+ 8 - 0
configs/am65x_evm_a53_defconfig

@@ -34,6 +34,8 @@ CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_REMOTEPROC=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TIME=y
 # CONFIG_ISO_PARTITION is not set
@@ -68,8 +70,14 @@ CONFIG_MMC_SDHCI_AM654=y
 CONFIG_PHY_TI=y
 CONFIG_PHY_FIXED=y
 CONFIG_DM_ETH=y
+CONFIG_E1000=y
+CONFIG_CMD_E1000=y
 CONFIG_TI_AM65_CPSW_NUSS=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_PCI_KEYSTONE=y
 CONFIG_PHY=y
+CONFIG_AM654_PHY=y
 CONFIG_PINCTRL=y
 # CONFIG_PINCTRL_GENERIC is not set
 CONFIG_SPL_PINCTRL=y

+ 109 - 0
configs/brsmarc1_defconfig

@@ -0,0 +1,109 @@
+CONFIG_ARM=y
+CONFIG_ARCH_OMAP2PLUS=y
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_AM33XX=y
+CONFIG_SYS_MPUCLK=600
+CONFIG_TARGET_BRSMARC1=y
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x20000
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x4000
+CONFIG_SPL=y
+CONFIG_ENV_SECT_SIZE=0x10000
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_TPL_SYS_MALLOC_F_LEN=0x0
+# CONFIG_EXPERT is not set
+# CONFIG_FIT is not set
+CONFIG_OF_BOARD_SETUP=y
+CONFIG_BOOTDELAY=0
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="run b_default"
+CONFIG_SYS_CONSOLE_IS_IN_ENV=y
+CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_VERSION_VARIABLE=y
+# CONFIG_DISPLAY_CPUINFO is not set
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_ARCH_MISC_INIT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_SEPARATE_BSS=y
+# CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR is not set
+CONFIG_SPL_I2C_SUPPORT=y
+# CONFIG_SPL_NAND_SUPPORT is not set
+CONFIG_SPL_POWER_SUPPORT=y
+CONFIG_SPL_SPI_LOAD=y
+CONFIG_SPL_YMODEM_SUPPORT=y
+CONFIG_HUSH_PARSER=y
+# CONFIG_CMD_BOOTD is not set
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_EDITENV is not set
+# CONFIG_CMD_CRC32 is not set
+CONFIG_CMD_CLK=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_ITEST is not set
+CONFIG_CMD_DHCP=y
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+# CONFIG_SPL_DOS_PARTITION is not set
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="am335x-brsmarc1"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_NETCONSOLE=y
+CONFIG_DM=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+# CONFIG_OF_TRANSLATE is not set
+# CONFIG_SPL_BLK is not set
+CONFIG_DM_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_MISC=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SF_DEFAULT_SPEED=24000000
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
+CONFIG_PHY_NATSEMI=y
+CONFIG_DM_ETH=y
+CONFIG_DRIVER_TI_CPSW=y
+CONFIG_DM_SERIAL=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_OMAP3_SPI=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_MUSB_HOST=y
+CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_TI=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+# CONFIG_OMAP_WATCHDOG is not set
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_SHA1=y
+CONFIG_SHA256=y
+# CONFIG_EFI_LOADER is not set

+ 11 - 6
configs/da850evm_direct_nor_defconfig

@@ -21,17 +21,18 @@ CONFIG_SYS_PROMPT="U-Boot > "
 CONFIG_CMD_IMLS=y
 CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_DM=y
-# CONFIG_CMD_GPIO is not set
 # CONFIG_CMD_GPT is not set
 # CONFIG_CMD_MMC is not set
+CONFIG_CMD_MTD=y
+CONFIG_CMD_NAND=y
 # CONFIG_CMD_PART is not set
+# CONFIG_CMD_SF is not set
 # CONFIG_CMD_SPI is not set
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_TIME is not set
-# CONFIG_CMD_EXT2 is not set
-# CONFIG_CMD_EXT4 is not set
-# CONFIG_CMD_FAT is not set
-# CONFIG_CMD_FS_GENERIC is not set
+CONFIG_CMD_MTDPARTS=y
+CONFIG_MTDIDS_DEFAULT="nor0=physmap-flash.2,nor1=spi1.0,nand0=nand512"
+CONFIG_MTDPARTS_DEFAULT="mtdparts=physmap-flash.2:1m(u-boot),128k(u-boot-env),-(spare);spi1.0:32k(SPL),480k(u-boot),64k(u-boot-env),7552k(kernel-spare),64k(MAC-Address);nand512:128k(u-boot env),512k(u-boot),128k(spl-os),8m(kernel),-(rootfs)"
 CONFIG_CMD_DIAG=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="da850-evm"
@@ -45,12 +46,17 @@ CONFIG_SYS_I2C_DAVINCI=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_FLASH_CFI_DRIVER=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_FLASH_CFI_MTD=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_NAND=y
+CONFIG_NAND_DAVINCI=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
 CONFIG_DM_ETH=y
 CONFIG_MII=y
 CONFIG_DRIVER_TI_EMAC=y
@@ -66,7 +72,6 @@ CONFIG_DM_SPI=y
 CONFIG_DAVINCI_SPI=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
-# CONFIG_SPL_DM_USB is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_DA8XX=y
 CONFIG_USB_MUSB_HOST=y

+ 13 - 0
drivers/clk/clk-uclass.c

@@ -518,6 +518,19 @@ int clk_get_by_id(ulong id, struct clk **clkp)
 	return -ENOENT;
 }
 
+bool clk_is_match(const struct clk *p, const struct clk *q)
+{
+	/* trivial case: identical struct clk's or both NULL */
+	if (p == q)
+		return true;
+
+	/* same device, id and data */
+	if (p->dev == q->dev && p->id == q->id && p->data == q->data)
+		return true;
+
+	return false;
+}
+
 UCLASS_DRIVER(clk) = {
 	.id		= UCLASS_CLK,
 	.name		= "clk",

+ 17 - 0
drivers/core/fdtaddr.c

@@ -129,6 +129,23 @@ fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name)
 #endif
 }
 
+fdt_addr_t devfdt_get_addr_size_name(struct udevice *dev, const char *name,
+				     fdt_size_t *size)
+{
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	int index;
+
+	index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
+				      "reg-names", name);
+	if (index < 0)
+		return index;
+
+	return devfdt_get_addr_size_index(dev, index, size);
+#else
+	return FDT_ADDR_T_NONE;
+#endif
+}
+
 fdt_addr_t devfdt_get_addr(struct udevice *dev)
 {
 	return devfdt_get_addr_index(dev, 0);

+ 20 - 0
drivers/core/read.c

@@ -82,6 +82,15 @@ fdt_addr_t dev_read_addr_index(struct udevice *dev, int index)
 		return devfdt_get_addr_index(dev, index);
 }
 
+fdt_addr_t dev_read_addr_size_index(struct udevice *dev, int index,
+				    fdt_size_t *size)
+{
+	if (ofnode_is_np(dev_ofnode(dev)))
+		return ofnode_get_addr_size_index(dev_ofnode(dev), index, size);
+	else
+		return devfdt_get_addr_size_index(dev, index, size);
+}
+
 void *dev_remap_addr_index(struct udevice *dev, int index)
 {
 	fdt_addr_t addr = dev_read_addr_index(dev, index);
@@ -102,6 +111,17 @@ fdt_addr_t dev_read_addr_name(struct udevice *dev, const char *name)
 		return dev_read_addr_index(dev, index);
 }
 
+fdt_addr_t dev_read_addr_size_name(struct udevice *dev, const char *name,
+				   fdt_size_t *size)
+{
+	int index = dev_read_stringlist_search(dev, "reg-names", name);
+
+	if (index < 0)
+		return FDT_ADDR_T_NONE;
+	else
+		return dev_read_addr_size_index(dev, index, size);
+}
+
 void *dev_remap_addr_name(struct udevice *dev, const char *name)
 {
 	fdt_addr_t addr = dev_read_addr_name(dev, name);

+ 10 - 3
drivers/firmware/ti_sci.c

@@ -3170,6 +3170,7 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
 	u32 resource_subtype;
 	u16 resource_type;
 	struct ti_sci_resource *res;
+	bool valid_set = false;
 	int sets, i, ret;
 	u32 *temp;
 
@@ -3209,12 +3210,15 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
 							&res->desc[i].start,
 							&res->desc[i].num);
 		if (ret) {
-			dev_err(dev, "type %d subtype %d not allocated for host %d\n",
+			dev_dbg(dev, "type %d subtype %d not allocated for host %d\n",
 				resource_type, resource_subtype,
 				handle_to_ti_sci_info(handle)->host_id);
-			return ERR_PTR(ret);
+			res->desc[i].start = 0;
+			res->desc[i].num = 0;
+			continue;
 		}
 
+		valid_set = true;
 		dev_dbg(dev, "res type = %d, subtype = %d, start = %d, num = %d\n",
 			resource_type, resource_subtype, res->desc[i].start,
 			res->desc[i].num);
@@ -3226,7 +3230,10 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
 			return ERR_PTR(-ENOMEM);
 	}
 
-	return res;
+	if (valid_set)
+		return res;
+
+	return ERR_PTR(-EINVAL);
 }
 
 /* Description for K2G */

+ 6 - 0
drivers/pci/Kconfig

@@ -145,4 +145,10 @@ config PCI_MVEBU
 	  Say Y here if you want to enable PCIe controller support on
 	  Armada XP/38x SoCs.
 
+config PCI_KEYSTONE
+	bool "TI Keystone PCIe controller"
+	depends on DM_PCI
+	help
+	  Say Y here if you want to enable PCI controller support on AM654 SoC.
+
 endif

+ 1 - 0
drivers/pci/Makefile

@@ -38,3 +38,4 @@ obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie_layerscape_gen4.o \
 				pcie_layerscape_gen4_fixup.o
 obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o
 obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o
+obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o

+ 725 - 0
drivers/pci/pcie_dw_ti.c

@@ -0,0 +1,725 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Texas Instruments, Inc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pci.h>
+#include <generic-phy.h>
+#include <power-domain.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm-generic/gpio.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define PCIE_VENDORID_MASK	GENMASK(15, 0)
+#define PCIE_DEVICEID_SHIFT	16
+
+/* PCI DBICS registers */
+#define PCIE_CONFIG_BAR0		0x10
+#define PCIE_LINK_STATUS_REG		0x80
+#define PCIE_LINK_STATUS_SPEED_OFF	16
+#define PCIE_LINK_STATUS_SPEED_MASK	(0xf << PCIE_LINK_STATUS_SPEED_OFF)
+#define PCIE_LINK_STATUS_WIDTH_OFF	20
+#define PCIE_LINK_STATUS_WIDTH_MASK	(0xf << PCIE_LINK_STATUS_WIDTH_OFF)
+
+#define PCIE_LINK_CAPABILITY		0x7c
+#define PCIE_LINK_CTL_2			0xa0
+#define TARGET_LINK_SPEED_MASK		0xf
+#define LINK_SPEED_GEN_1		0x1
+#define LINK_SPEED_GEN_2		0x2
+#define LINK_SPEED_GEN_3		0x3
+
+#define PCIE_MISC_CONTROL_1_OFF		0x8bc
+#define PCIE_DBI_RO_WR_EN		BIT(0)
+
+#define PLR_OFFSET			0x700
+#define PCIE_PORT_DEBUG0		(PLR_OFFSET + 0x28)
+#define PORT_LOGIC_LTSSM_STATE_MASK	0x1f
+#define PORT_LOGIC_LTSSM_STATE_L0	0x11
+
+#define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80c
+#define PORT_LOGIC_SPEED_CHANGE		(0x1 << 17)
+
+#define PCIE_LINK_UP_TIMEOUT_MS		100
+
+/*
+ * iATU Unroll-specific register definitions
+ * From 4.80 core version the address translation will be made by unroll.
+ * The registers are offset from atu_base
+ */
+#define PCIE_ATU_UNR_REGION_CTRL1	0x00
+#define PCIE_ATU_UNR_REGION_CTRL2	0x04
+#define PCIE_ATU_UNR_LOWER_BASE		0x08
+#define PCIE_ATU_UNR_UPPER_BASE		0x0c
+#define PCIE_ATU_UNR_LIMIT		0x10
+#define PCIE_ATU_UNR_LOWER_TARGET	0x14
+#define PCIE_ATU_UNR_UPPER_TARGET	0x18
+
+#define PCIE_ATU_REGION_INDEX1		(0x1 << 0)
+#define PCIE_ATU_REGION_INDEX0		(0x0 << 0)
+#define PCIE_ATU_TYPE_MEM		(0x0 << 0)
+#define PCIE_ATU_TYPE_IO		(0x2 << 0)
+#define PCIE_ATU_TYPE_CFG0		(0x4 << 0)
+#define PCIE_ATU_TYPE_CFG1		(0x5 << 0)
+#define PCIE_ATU_ENABLE			(0x1 << 31)
+#define PCIE_ATU_BAR_MODE_ENABLE	(0x1 << 30)
+#define PCIE_ATU_BUS(x)			(((x) & 0xff) << 24)
+#define PCIE_ATU_DEV(x)			(((x) & 0x1f) << 19)
+#define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
+
+/* Register address builder */
+#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region)	((region) << 9)
+
+/* Offsets from App base */
+#define PCIE_CMD_STATUS			0x04
+#define LTSSM_EN_VAL			BIT(0)
+
+/* Parameters for the waiting for iATU enabled routine */
+#define LINK_WAIT_MAX_IATU_RETRIES	5
+#define LINK_WAIT_IATU			10000
+
+#define AM654_PCIE_DEV_TYPE_MASK	0x3
+#define EP				0x0
+#define LEG_EP				0x1
+#define RC				0x2
+
+/**
+ * struct pcie_dw_ti - TI DW PCIe controller state
+ *
+ * @app_base: The base address of application register space
+ * @dbics_base: The base address of dbics register space
+ * @cfg_base: The base address of configuration space
+ * @atu_base: The base address of ATU space
+ * @cfg_size: The size of the configuration space which is needed
+ *            as it gets written into the PCIE_ATU_LIMIT register
+ * @first_busno: This driver supports multiple PCIe controllers.
+ *               first_busno stores the bus number of the PCIe root-port
+ *               number which may vary depending on the PCIe setup
+ *               (PEX switches etc).
+ */
+struct pcie_dw_ti {
+	void *app_base;
+	void *dbi_base;
+	void *cfg_base;
+	void *atu_base;
+	fdt_size_t cfg_size;
+	int first_busno;
+	struct udevice *dev;
+
+	/* IO and MEM PCI regions */
+	struct pci_region io;
+	struct pci_region mem;
+};
+
+enum dw_pcie_device_mode {
+	DW_PCIE_UNKNOWN_TYPE,
+	DW_PCIE_EP_TYPE,
+	DW_PCIE_LEG_EP_TYPE,
+	DW_PCIE_RC_TYPE,
+};
+
+static int pcie_dw_get_link_speed(struct pcie_dw_ti *pci)
+{
+	return (readl(pci->dbi_base + PCIE_LINK_STATUS_REG) &
+		PCIE_LINK_STATUS_SPEED_MASK) >> PCIE_LINK_STATUS_SPEED_OFF;
+}
+
+static int pcie_dw_get_link_width(struct pcie_dw_ti *pci)
+{
+	return (readl(pci->dbi_base + PCIE_LINK_STATUS_REG) &
+		PCIE_LINK_STATUS_WIDTH_MASK) >> PCIE_LINK_STATUS_WIDTH_OFF;
+}
+
+static void dw_pcie_writel_ob_unroll(struct pcie_dw_ti *pci, u32 index, u32 reg,
+				     u32 val)
+{
+	u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
+	void __iomem *base = pci->atu_base;
+
+	writel(val, base + offset + reg);
+}
+
+static u32 dw_pcie_readl_ob_unroll(struct pcie_dw_ti *pci, u32 index, u32 reg)
+{
+	u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
+	void __iomem *base = pci->atu_base;
+
+	return readl(base + offset + reg);
+}
+
+/**
+ * pcie_dw_prog_outbound_atu_unroll() - Configure ATU for outbound accesses
+ *
+ * @pcie: Pointer to the PCI controller state
+ * @index: ATU region index
+ * @type: ATU accsess type
+ * @cpu_addr: the physical address for the translation entry
+ * @pci_addr: the pcie bus address for the translation entry
+ * @size: the size of the translation entry
+ */
+static void pcie_dw_prog_outbound_atu_unroll(struct pcie_dw_ti *pci, int index,
+					     int type, u64 cpu_addr,
+					     u64 pci_addr, u32 size)
+{
+	u32 retries, val;
+
+	debug("ATU programmed with: index: %d, type: %d, cpu addr: %8llx, pci addr: %8llx, size: %8x\n",
+	      index, type, cpu_addr, pci_addr, size);
+
+	dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
+				 lower_32_bits(cpu_addr));
+	dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
+				 upper_32_bits(cpu_addr));
+	dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LIMIT,
+				 lower_32_bits(cpu_addr + size - 1));
+	dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
+				 lower_32_bits(pci_addr));
+	dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
+				 upper_32_bits(pci_addr));
+	dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
+				 type);
+	dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
+				 PCIE_ATU_ENABLE);
+
+	/*
+	 * Make sure ATU enable takes effect before any subsequent config
+	 * and I/O accesses.
+	 */
+	for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
+		val = dw_pcie_readl_ob_unroll(pci, index,
+					      PCIE_ATU_UNR_REGION_CTRL2);
+		if (val & PCIE_ATU_ENABLE)
+			return;
+
+		udelay(LINK_WAIT_IATU);
+	}
+	dev_err(pci->dev, "outbound iATU is not being enabled\n");
+}
+
+/**
+ * set_cfg_address() - Configure the PCIe controller config space access
+ *
+ * @pcie: Pointer to the PCI controller state
+ * @d: PCI device to access
+ * @where: Offset in the configuration space
+ *
+ * Configures the PCIe controller to access the configuration space of
+ * a specific PCIe device and returns the address to use for this
+ * access.
+ *
+ * Return: Address that can be used to access the configation space
+ *         of the requested device / offset
+ */
+static uintptr_t set_cfg_address(struct pcie_dw_ti *pcie,
+				 pci_dev_t d, uint where)
+{
+	int bus = PCI_BUS(d) - pcie->first_busno;
+	uintptr_t va_address;
+	u32 atu_type;
+
+	/* Use dbi_base for own configuration read and write */
+	if (!bus) {
+		va_address = (uintptr_t)pcie->dbi_base;
+		goto out;
+	}
+
+	if (bus == 1)
+		/* For local bus, change TLP Type field to 4. */
+		atu_type = PCIE_ATU_TYPE_CFG0;
+	else
+		/* Otherwise, change TLP Type field to 5. */
+		atu_type = PCIE_ATU_TYPE_CFG1;
+
+	/*
+	 * Not accessing root port configuration space?
+	 * Region #0 is used for Outbound CFG space access.
+	 * Direction = Outbound
+	 * Region Index = 0
+	 */
+	d = PCI_MASK_BUS(d);
+	d = PCI_ADD_BUS(bus, d);
+	pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
+					 atu_type, (u64)pcie->cfg_base,
+					 d << 8, pcie->cfg_size);
+
+	va_address = (uintptr_t)pcie->cfg_base;
+
+out:
+	va_address += where & ~0x3;
+
+	return va_address;
+}
+
+/**
+ * pcie_dw_addr_valid() - Check for valid bus address
+ *
+ * @d: The PCI device to access
+ * @first_busno: Bus number of the PCIe controller root complex
+ *
+ * Return 1 (true) if the PCI device can be accessed by this controller.
+ *
+ * Return: 1 on valid, 0 on invalid
+ */
+static int pcie_dw_addr_valid(pci_dev_t d, int first_busno)
+{
+	if ((PCI_BUS(d) == first_busno) && (PCI_DEV(d) > 0))
+		return 0;
+	if ((PCI_BUS(d) == first_busno + 1) && (PCI_DEV(d) > 0))
+		return 0;
+
+	return 1;
+}
+
+/**
+ * pcie_dw_ti_read_config() - Read from configuration space
+ *
+ * @bus: Pointer to the PCI bus
+ * @bdf: Identifies the PCIe device to access
+ * @offset: The offset into the device's configuration space
+ * @valuep: A pointer at which to store the read value
+ * @size: Indicates the size of access to perform
+ *
+ * Read a value of size @size from offset @offset within the configuration
+ * space of the device identified by the bus, device & function numbers in @bdf
+ * on the PCI bus @bus.
+ *
+ * Return: 0 on success
+ */
+static int pcie_dw_ti_read_config(struct udevice *bus, pci_dev_t bdf,
+				  uint offset, ulong *valuep,
+				  enum pci_size_t size)
+{
+	struct pcie_dw_ti *pcie = dev_get_priv(bus);
+	uintptr_t va_address;
+	ulong value;
+
+	debug("PCIE CFG read: bdf=%2x:%2x:%2x ",
+	      PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
+
+	if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) {
+		debug("- out of range\n");
+		*valuep = pci_get_ff(size);
+		return 0;
+	}
+
+	va_address = set_cfg_address(pcie, bdf, offset);
+
+	value = readl(va_address);
+
+	debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
+	*valuep = pci_conv_32_to_size(value, offset, size);
+
+	pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
+					 PCIE_ATU_TYPE_IO, pcie->io.phys_start,
+					 pcie->io.bus_start, pcie->io.size);
+
+	return 0;
+}
+
+/**
+ * pcie_dw_ti_write_config() - Write to configuration space
+ *
+ * @bus: Pointer to the PCI bus
+ * @bdf: Identifies the PCIe device to access
+ * @offset: The offset into the device's configuration space
+ * @value: The value to write
+ * @size: Indicates the size of access to perform
+ *
+ * Write the value @value of size @size from offset @offset within the
+ * configuration space of the device identified by the bus, device & function
+ * numbers in @bdf on the PCI bus @bus.
+ *
+ * Return: 0 on success
+ */
+static int pcie_dw_ti_write_config(struct udevice *bus, pci_dev_t bdf,
+				   uint offset, ulong value,
+				   enum pci_size_t size)
+{
+	struct pcie_dw_ti *pcie = dev_get_priv(bus);
+	uintptr_t va_address;
+	ulong old;
+
+	debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ",
+	      PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
+	debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
+
+	if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) {
+		debug("- out of range\n");
+		return 0;
+	}
+
+	va_address = set_cfg_address(pcie, bdf, offset);
+
+	old = readl(va_address);
+	value = pci_conv_size_to_32(old, value, offset, size);
+	writel(value, va_address);
+
+	pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
+					 PCIE_ATU_TYPE_IO, pcie->io.phys_start,
+					 pcie->io.bus_start, pcie->io.size);
+
+	return 0;
+}
+
+static inline void dw_pcie_dbi_write_enable(struct pcie_dw_ti *pci, bool en)
+{
+	u32 val;
+
+	val = readl(pci->dbi_base + PCIE_MISC_CONTROL_1_OFF);
+	if (en)
+		val |= PCIE_DBI_RO_WR_EN;
+	else
+		val &= ~PCIE_DBI_RO_WR_EN;
+	writel(val, pci->dbi_base + PCIE_MISC_CONTROL_1_OFF);
+}
+
+/**
+ * pcie_dw_configure() - Configure link capabilities and speed
+ *
+ * @regs_base: A pointer to the PCIe controller registers
+ * @cap_speed: The capabilities and speed to configure
+ *
+ * Configure the link capabilities and speed in the PCIe root complex.
+ */
+static void pcie_dw_configure(struct pcie_dw_ti *pci, u32 cap_speed)
+{
+	u32 val;
+
+	dw_pcie_dbi_write_enable(pci, true);
+
+	val = readl(pci->dbi_base + PCIE_LINK_CAPABILITY);
+	val &= ~TARGET_LINK_SPEED_MASK;
+	val |= cap_speed;
+	writel(val, pci->dbi_base + PCIE_LINK_CAPABILITY);
+
+	val = readl(pci->dbi_base + PCIE_LINK_CTL_2);
+	val &= ~TARGET_LINK_SPEED_MASK;
+	val |= cap_speed;
+	writel(val, pci->dbi_base + PCIE_LINK_CTL_2);
+
+	dw_pcie_dbi_write_enable(pci, false);
+}
+
+/**
+ * is_link_up() - Return the link state
+ *
+ * @regs_base: A pointer to the PCIe DBICS registers
+ *
+ * Return: 1 (true) for active line and 0 (false) for no link
+ */
+static int is_link_up(struct pcie_dw_ti *pci)
+{
+	u32 val;
+
+	val = readl(pci->dbi_base + PCIE_PORT_DEBUG0);
+	val &= PORT_LOGIC_LTSSM_STATE_MASK;
+
+	return (val == PORT_LOGIC_LTSSM_STATE_L0);
+}
+
+/**
+ * wait_link_up() - Wait for the link to come up
+ *
+ * @regs_base: A pointer to the PCIe controller registers
+ *
+ * Return: 1 (true) for active line and 0 (false) for no link (timeout)
+ */
+static int wait_link_up(struct pcie_dw_ti *pci)
+{
+	unsigned long timeout;
+
+	timeout = get_timer(0) + PCIE_LINK_UP_TIMEOUT_MS;
+	while (!is_link_up(pci)) {
+		if (get_timer(0) > timeout)
+			return 0;
+	};
+
+	return 1;
+}
+
+static int pcie_dw_ti_pcie_link_up(struct pcie_dw_ti *pci, u32 cap_speed)
+{
+	u32 val;
+
+	if (is_link_up(pci)) {
+		printf("PCI Link already up before configuration!\n");
+		return 1;
+	}
+
+	/* DW pre link configurations */
+	pcie_dw_configure(pci, cap_speed);
+
+	/* Initiate link training */
+	val = readl(pci->app_base + PCIE_CMD_STATUS);
+	val |= LTSSM_EN_VAL;
+	writel(val, pci->app_base + PCIE_CMD_STATUS);
+
+	/* Check that link was established */
+	if (!wait_link_up(pci))
+		return 0;
+
+	/*
+	 * Link can be established in Gen 1. still need to wait
+	 * till MAC nagaotiation is completed
+	 */
+	udelay(100);
+
+	return 1;
+}
+
+/**
+ * pcie_dw_setup_host() - Setup the PCIe controller for RC opertaion
+ *
+ * @pcie: Pointer to the PCI controller state
+ *
+ * Configure the host BARs of the PCIe controller root port so that
+ * PCI(e) devices may access the system memory.
+ */
+static void pcie_dw_setup_host(struct pcie_dw_ti *pci)
+{
+	u32 val;
+
+	/* setup RC BARs */
+	writel(PCI_BASE_ADDRESS_MEM_TYPE_64,
+	       pci->dbi_base + PCI_BASE_ADDRESS_0);
+	writel(0x0, pci->dbi_base + PCI_BASE_ADDRESS_1);
+
+	/* setup interrupt pins */
+	dw_pcie_dbi_write_enable(pci, true);
+	val = readl(pci->dbi_base + PCI_INTERRUPT_LINE);
+	val &= 0xffff00ff;
+	val |= 0x00000100;
+	writel(val, pci->dbi_base + PCI_INTERRUPT_LINE);
+	dw_pcie_dbi_write_enable(pci, false);
+
+	/* setup bus numbers */
+	val = readl(pci->dbi_base + PCI_PRIMARY_BUS);
+	val &= 0xff000000;
+	val |= 0x00ff0100;
+	writel(val, pci->dbi_base + PCI_PRIMARY_BUS);
+
+	/* setup command register */
+	val = readl(pci->dbi_base + PCI_COMMAND);
+	val &= 0xffff0000;
+	val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+		PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
+	writel(val, pci->dbi_base + PCI_COMMAND);
+
+	/* Enable write permission for the DBI read-only register */
+	dw_pcie_dbi_write_enable(pci, true);
+	/* program correct class for RC */
+	writew(PCI_CLASS_BRIDGE_PCI, pci->dbi_base + PCI_CLASS_DEVICE);
+	/* Better disable write permission right after the update */
+	dw_pcie_dbi_write_enable(pci, false);
+
+	val = readl(pci->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
+	val |= PORT_LOGIC_SPEED_CHANGE;
+	writel(val, pci->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
+}
+
+static int pcie_am654_set_mode(struct pcie_dw_ti *pci,
+			       enum dw_pcie_device_mode mode)
+{
+	struct regmap *syscon;
+	u32 val;
+	u32 mask;
+	int ret;
+
+	syscon = syscon_regmap_lookup_by_phandle(pci->dev,
+						 "ti,syscon-pcie-mode");
+	if (IS_ERR(syscon))
+		return 0;
+
+	mask = AM654_PCIE_DEV_TYPE_MASK;
+
+	switch (mode) {
+	case DW_PCIE_RC_TYPE:
+		val = RC;
+		break;
+	case DW_PCIE_EP_TYPE:
+		val = EP;
+		break;
+	default:
+		dev_err(pci->dev, "INVALID device type %d\n", mode);
+		return -EINVAL;
+	}
+
+	ret = regmap_update_bits(syscon, 0, mask, val);
+	if (ret) {
+		dev_err(pci->dev, "failed to set pcie mode\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pcie_dw_init_id(struct pcie_dw_ti *pci)
+{
+	struct regmap *devctrl_regs;
+	unsigned int id;
+	int ret;
+
+	devctrl_regs = syscon_regmap_lookup_by_phandle(pci->dev,
+						       "ti,syscon-pcie-id");
+	if (IS_ERR(devctrl_regs))
+		return PTR_ERR(devctrl_regs);
+
+	ret = regmap_read(devctrl_regs, 0, &id);
+	if (ret)
+		return ret;
+
+	dw_pcie_dbi_write_enable(pci, true);
+	writew(id & PCIE_VENDORID_MASK, pci->dbi_base + PCI_VENDOR_ID);
+	writew(id >> PCIE_DEVICEID_SHIFT, pci->dbi_base + PCI_DEVICE_ID);
+	dw_pcie_dbi_write_enable(pci, false);
+
+	return 0;
+}
+
+/**
+ * pcie_dw_ti_probe() - Probe the PCIe bus for active link
+ *
+ * @dev: A pointer to the device being operated on
+ *
+ * Probe for an active link on the PCIe bus and configure the controller
+ * to enable this port.
+ *
+ * Return: 0 on success, else -ENODEV
+ */
+static int pcie_dw_ti_probe(struct udevice *dev)
+{
+	struct pcie_dw_ti *pci = dev_get_priv(dev);
+	struct udevice *ctlr = pci_get_controller(dev);
+	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
+	struct power_domain pci_pwrdmn;
+	struct phy phy0, phy1;
+	int ret;
+
+	ret = power_domain_get_by_index(dev, &pci_pwrdmn, 0);
+	if (ret) {
+		dev_err(dev, "failed to get power domain\n");
+		return ret;
+	}
+
+	ret = power_domain_on(&pci_pwrdmn);
+	if (ret) {
+		dev_err(dev, "Power domain on failed\n");
+		return ret;
+	}
+
+	ret = generic_phy_get_by_name(dev,  "pcie-phy0", &phy0);
+	if (ret) {
+		dev_err(dev, "Unable to get phy0");
+		return ret;
+	}
+	generic_phy_reset(&phy0);
+	generic_phy_init(&phy0);
+	generic_phy_power_on(&phy0);
+
+	ret = generic_phy_get_by_name(dev,  "pcie-phy1", &phy1);
+	if (ret) {
+		dev_err(dev, "Unable to get phy1");
+		return ret;
+	}
+	generic_phy_reset(&phy1);
+	generic_phy_init(&phy1);
+	generic_phy_power_on(&phy1);
+
+	pci->first_busno = dev->seq;
+	pci->dev = dev;
+
+	pcie_dw_setup_host(pci);
+	pcie_dw_init_id(pci);
+
+	if (device_is_compatible(dev, "ti,am654-pcie-rc"))
+		pcie_am654_set_mode(pci, DW_PCIE_RC_TYPE);
+
+	if (!pcie_dw_ti_pcie_link_up(pci, LINK_SPEED_GEN_2)) {
+		printf("PCIE-%d: Link down\n", dev->seq);
+		return -ENODEV;
+	}
+
+	printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n", dev->seq,
+	       pcie_dw_get_link_speed(pci),
+	       pcie_dw_get_link_width(pci),
+	       hose->first_busno);
+
+	/* Store the IO and MEM windows settings for future use by the ATU */
+	pci->io.phys_start = hose->regions[0].phys_start; /* IO base */
+	pci->io.bus_start  = hose->regions[0].bus_start;  /* IO_bus_addr */
+	pci->io.size	    = hose->regions[0].size;	   /* IO size */
+
+	pci->mem.phys_start = hose->regions[1].phys_start; /* MEM base */
+	pci->mem.bus_start  = hose->regions[1].bus_start;  /* MEM_bus_addr */
+	pci->mem.size	     = hose->regions[1].size;	    /* MEM size */
+
+	pcie_dw_prog_outbound_atu_unroll(pci, PCIE_ATU_REGION_INDEX0,
+					 PCIE_ATU_TYPE_MEM,
+					 pci->mem.phys_start,
+					 pci->mem.bus_start, pci->mem.size);
+
+	return 0;
+}
+
+/**
+ * pcie_dw_ti_ofdata_to_platdata() - Translate from DT to device state
+ *
+ * @dev: A pointer to the device being operated on
+ *
+ * Translate relevant data from the device tree pertaining to device @dev into
+ * state that the driver will later make use of. This state is stored in the
+ * device's private data structure.
+ *
+ * Return: 0 on success, else -EINVAL
+ */
+static int pcie_dw_ti_ofdata_to_platdata(struct udevice *dev)
+{
+	struct pcie_dw_ti *pcie = dev_get_priv(dev);
+
+	/* Get the controller base address */
+	pcie->dbi_base = (void *)dev_read_addr_name(dev, "dbics");
+	if ((fdt_addr_t)pcie->dbi_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* Get the config space base address and size */
+	pcie->cfg_base = (void *)dev_read_addr_size_name(dev, "config",
+							 &pcie->cfg_size);
+	if ((fdt_addr_t)pcie->cfg_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* Get the iATU base address and size */
+	pcie->atu_base = (void *)dev_read_addr_name(dev, "atu");
+	if ((fdt_addr_t)pcie->atu_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* Get the app base address and size */
+	pcie->app_base = (void *)dev_read_addr_name(dev, "app");
+	if ((fdt_addr_t)pcie->app_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct dm_pci_ops pcie_dw_ti_ops = {
+	.read_config	= pcie_dw_ti_read_config,
+	.write_config	= pcie_dw_ti_write_config,
+};
+
+static const struct udevice_id pcie_dw_ti_ids[] = {
+	{ .compatible = "ti,am654-pcie-rc" },
+	{ }
+};
+
+U_BOOT_DRIVER(pcie_dw_ti) = {
+	.name			= "pcie_dw_ti",
+	.id			= UCLASS_PCI,
+	.of_match		= pcie_dw_ti_ids,
+	.ops			= &pcie_dw_ti_ops,
+	.ofdata_to_platdata	= pcie_dw_ti_ofdata_to_platdata,
+	.probe			= pcie_dw_ti_probe,
+	.priv_auto_alloc_size	= sizeof(struct pcie_dw_ti),
+};

+ 9 - 0
drivers/phy/Kconfig

@@ -108,6 +108,15 @@ config SPL_PIPE3_PHY
 	  This PHY is found on omap devices supporting SATA such as dra7, am57x
 	  and omap5
 
+config AM654_PHY
+	tristate "TI AM654 SERDES support"
+	depends on PHY && ARCH_K3
+	select REGMAP
+	select SYSCON
+	help
+	  This option enables support for TI AM654 SerDes PHY used for
+	  PCIe.
+
 config STI_USB_PHY
 	bool "STMicroelectronics USB2 picoPHY driver for STiH407 family"
 	depends on PHY && ARCH_STI

+ 1 - 0
drivers/phy/Makefile

@@ -11,6 +11,7 @@ obj-$(CONFIG_BCM6358_USBH_PHY) += bcm6358-usbh-phy.o
 obj-$(CONFIG_BCM6368_USBH_PHY) += bcm6368-usbh-phy.o
 obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o
 obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o
+obj-$(CONFIG_AM654_PHY) += phy-ti-am654.o
 obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o
 obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
 obj-$(CONFIG_PHY_RCAR_GEN3) += phy-rcar-gen3.o

+ 411 - 0
drivers/phy/phy-ti-am654.c

@@ -0,0 +1,411 @@
+// SPDX-License-Identifier: GPL-2.0+
+/**
+ * PCIe SERDES driver for AM654x SoC
+ *
+ * Copyright (C) 2018 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dm/device.h>
+#include <dm/lists.h>
+#include <dt-bindings/phy/phy.h>
+#include <generic-phy.h>
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+#include <power-domain.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#define CMU_R07C		0x7c
+#define CMU_MASTER_CDN_O	BIT(24)
+
+#define COMLANE_R138		0xb38
+#define CONFIG_VERSION_REG_MASK	GENMASK(23, 16)
+#define CONFIG_VERSION_REG_SHIFT 16
+#define VERSION			0x70
+
+#define COMLANE_R190		0xb90
+#define L1_MASTER_CDN_O		BIT(9)
+
+#define COMLANE_R194		0xb94
+#define CMU_OK_I_0		BIT(19)
+
+#define SERDES_CTRL		0x1fd0
+#define POR_EN			BIT(29)
+
+#define WIZ_LANEXCTL_STS	0x1fe0
+#define TX0_ENABLE_OVL		BIT(31)
+#define TX0_ENABLE_MASK		GENMASK(30, 29)
+#define TX0_ENABLE_SHIFT	29
+#define TX0_DISABLE_STATE	0x0
+#define TX0_SLEEP_STATE		0x1
+#define TX0_SNOOZE_STATE	0x2
+#define TX0_ENABLE_STATE	0x3
+#define RX0_ENABLE_OVL		BIT(15)
+#define RX0_ENABLE_MASK		GENMASK(14, 13)
+#define RX0_ENABLE_SHIFT	13
+#define RX0_DISABLE_STATE	0x0
+#define RX0_SLEEP_STATE		0x1
+#define RX0_SNOOZE_STATE	0x2
+#define RX0_ENABLE_STATE	0x3
+
+#define WIZ_PLL_CTRL		0x1ff4
+#define PLL_ENABLE_OVL		BIT(31)
+#define PLL_ENABLE_MASK		GENMASK(30, 29)
+#define PLL_ENABLE_SHIFT	29
+#define PLL_DISABLE_STATE	0x0
+#define PLL_SLEEP_STATE		0x1
+#define PLL_SNOOZE_STATE	0x2
+#define PLL_ENABLE_STATE	0x3
+#define PLL_OK			BIT(28)
+
+#define PLL_LOCK_TIME		1000	/* in milliseconds */
+#define SLEEP_TIME		100	/* in microseconds */
+
+#define LANE_USB3		0x0
+#define LANE_PCIE0_LANE0	0x1
+
+#define LANE_PCIE1_LANE0	0x0
+#define LANE_PCIE0_LANE1	0x1
+
+#define SERDES_NUM_CLOCKS	3
+
+/* SERDES control MMR bit offsets */
+#define SERDES_CTL_LANE_FUNC_SEL_SHIFT	0
+#define SERDES_CTL_LANE_FUNC_SEL_MASK	GENMASK(1, 0)
+#define SERDES_CTL_CLK_SEL_SHIFT	4
+#define SERDES_CTL_CLK_SEL_MASK		GENMASK(7, 4)
+
+/**
+ * struct serdes_am654_mux_clk_data - clock controller information structure
+ */
+struct serdes_am654_mux_clk_data {
+	struct regmap *regmap;
+	struct clk_bulk parents;
+};
+
+static int serdes_am654_mux_clk_probe(struct udevice *dev)
+{
+	struct serdes_am654_mux_clk_data *data = dev_get_priv(dev);
+	struct udevice *syscon;
+	struct regmap *regmap;
+	int ret;
+
+	debug("%s(dev=%s)\n", __func__, dev->name);
+
+	if (!data)
+		return -ENOMEM;
+
+	ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
+					   "ti,serdes-clk", &syscon);
+	if (ret) {
+		dev_err(dev, "unable to find syscon device\n");
+		return ret;
+	}
+
+	regmap = syscon_get_regmap(syscon);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "Fail to get Syscon regmap\n");
+		return PTR_ERR(regmap);
+	}
+
+	data->regmap = regmap;
+
+	ret = clk_get_bulk(dev, &data->parents);
+	if (ret) {
+		dev_err(dev, "Failed to obtain parent clocks\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mux_table[SERDES_NUM_CLOCKS][3] = {
+	/*
+	 * The entries represent values for selecting between
+	 * {left input, external reference clock, right input}
+	 * Only one of Left Output or Right Output should be used since
+	 * both left and right output clock uses the same bits and modifying
+	 * one clock will impact the other.
+	 */
+	{ BIT(2),               0, BIT(0) }, /* Mux of CMU refclk */
+	{     -1,          BIT(3), BIT(1) }, /* Mux of Left Output */
+	{ BIT(1), BIT(3) | BIT(1),     -1 }, /* Mux of Right Output */
+};
+
+static int serdes_am654_mux_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct serdes_am654_mux_clk_data *data = dev_get_priv(clk->dev);
+	u32 val;
+	int i;
+
+	debug("%s(clk=%s, parent=%s)\n", __func__, clk->dev->name,
+	      parent->dev->name);
+
+	/*
+	 * Since we have the same device-tree node represent both the
+	 * clock and serdes device, we have two devices associated with
+	 * the serdes node. assigned-clocks for this node is processed twice,
+	 * once for the clock device and another time for the serdes
+	 * device. When it is processed for the clock device, it is before
+	 * the probe for clock device has been called. We ignore this case
+	 * and rely on assigned-clocks to be processed correctly for the
+	 * serdes case.
+	 */
+	if (!data->regmap)
+		return 0;
+
+	for (i = 0; i < data->parents.count; i++) {
+		if (clk_is_match(&data->parents.clks[i], parent))
+			break;
+	}
+
+	if (i >= data->parents.count)
+		return -EINVAL;
+
+	val = mux_table[clk->id][i];
+	val <<= SERDES_CTL_CLK_SEL_SHIFT;
+
+	regmap_update_bits(data->regmap, 0, SERDES_CTL_CLK_SEL_MASK, val);
+
+	return 0;
+}
+
+static struct clk_ops serdes_am654_mux_clk_ops = {
+	.set_parent = serdes_am654_mux_clk_set_parent,
+};
+
+U_BOOT_DRIVER(serdes_am654_mux_clk) = {
+	.name = "ti-serdes-am654-mux-clk",
+	.id = UCLASS_CLK,
+	.probe = serdes_am654_mux_clk_probe,
+	.priv_auto_alloc_size = sizeof(struct serdes_am654_mux_clk_data),
+	.ops = &serdes_am654_mux_clk_ops,
+};
+
+struct serdes_am654 {
+	struct regmap *regmap;
+	struct regmap *serdes_ctl;
+};
+
+static int serdes_am654_enable_pll(struct serdes_am654 *phy)
+{
+	u32 mask = PLL_ENABLE_OVL | PLL_ENABLE_MASK;
+	u32 val = PLL_ENABLE_OVL | (PLL_ENABLE_STATE << PLL_ENABLE_SHIFT);
+
+	regmap_update_bits(phy->regmap, WIZ_PLL_CTRL, mask, val);
+
+	return regmap_read_poll_timeout(phy->regmap, WIZ_PLL_CTRL, val,
+					val & PLL_OK, 1000, PLL_LOCK_TIME);
+}
+
+static void serdes_am654_disable_pll(struct serdes_am654 *phy)
+{
+	u32 mask = PLL_ENABLE_OVL | PLL_ENABLE_MASK;
+
+	regmap_update_bits(phy->regmap, WIZ_PLL_CTRL, mask, 0);
+}
+
+static int serdes_am654_enable_txrx(struct serdes_am654 *phy)
+{
+	u32 mask;
+	u32 val;
+
+	/* Enable TX */
+	mask = TX0_ENABLE_OVL | TX0_ENABLE_MASK;
+	val = TX0_ENABLE_OVL | (TX0_ENABLE_STATE << TX0_ENABLE_SHIFT);
+	regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, val);
+
+	/* Enable RX */
+	mask = RX0_ENABLE_OVL | RX0_ENABLE_MASK;
+	val = RX0_ENABLE_OVL | (RX0_ENABLE_STATE << RX0_ENABLE_SHIFT);
+	regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, val);
+
+	return 0;
+}
+
+static int serdes_am654_disable_txrx(struct serdes_am654 *phy)
+{
+	u32 mask;
+
+	/* Disable TX */
+	mask = TX0_ENABLE_OVL | TX0_ENABLE_MASK;
+	regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, 0);
+
+	/* Disable RX */
+	mask = RX0_ENABLE_OVL | RX0_ENABLE_MASK;
+	regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, 0);
+
+	return 0;
+}
+
+static int serdes_am654_power_on(struct phy *x)
+{
+	struct serdes_am654 *phy = dev_get_priv(x->dev);
+	int ret;
+	u32 val;
+
+	ret = serdes_am654_enable_pll(phy);
+	if (ret) {
+		dev_err(x->dev, "Failed to enable PLL\n");
+		return ret;
+	}
+
+	ret = serdes_am654_enable_txrx(phy);
+	if (ret) {
+		dev_err(x->dev, "Failed to enable TX RX\n");
+		return ret;
+	}
+
+	return regmap_read_poll_timeout(phy->regmap, COMLANE_R194, val,
+					val & CMU_OK_I_0, SLEEP_TIME,
+					PLL_LOCK_TIME);
+}
+
+static int serdes_am654_power_off(struct phy *x)
+{
+	struct serdes_am654 *phy = dev_get_priv(x->dev);
+
+	serdes_am654_disable_txrx(phy);
+	serdes_am654_disable_pll(phy);
+
+	return 0;
+}
+
+static int serdes_am654_init(struct phy *x)
+{
+	struct serdes_am654 *phy = dev_get_priv(x->dev);
+	u32 mask;
+	u32 val;
+
+	mask = CONFIG_VERSION_REG_MASK;
+	val = VERSION << CONFIG_VERSION_REG_SHIFT;
+	regmap_update_bits(phy->regmap, COMLANE_R138, mask, val);
+
+	val = CMU_MASTER_CDN_O;
+	regmap_update_bits(phy->regmap, CMU_R07C, val, val);
+
+	val = L1_MASTER_CDN_O;
+	regmap_update_bits(phy->regmap, COMLANE_R190, val, val);
+
+	return 0;
+}
+
+static int serdes_am654_reset(struct phy *x)
+{
+	struct serdes_am654 *phy = dev_get_priv(x->dev);
+	u32 val;
+
+	val = POR_EN;
+	regmap_update_bits(phy->regmap, SERDES_CTRL, val, val);
+	mdelay(1);
+	regmap_update_bits(phy->regmap, SERDES_CTRL, val, 0);
+
+	return 0;
+}
+
+static int serdes_am654_of_xlate(struct phy *x,
+				 struct ofnode_phandle_args *args)
+{
+	struct serdes_am654 *phy = dev_get_priv(x->dev);
+
+	if (args->args_count != 2) {
+		dev_err(phy->dev, "Invalid DT PHY argument count: %d\n",
+			args->args_count);
+		return -EINVAL;
+	}
+
+	if (args->args[0] != PHY_TYPE_PCIE) {
+		dev_err(phy->dev, "Unrecognized PHY type: %d\n",
+			args->args[0]);
+		return -EINVAL;
+	}
+
+	x->id = args->args[0] | (args->args[1] << 16);
+
+	/* Setup mux mode using second argument */
+	regmap_update_bits(phy->serdes_ctl, 0, SERDES_CTL_LANE_FUNC_SEL_MASK,
+			   args->args[1]);
+
+	return 0;
+}
+
+static int serdes_am654_bind(struct udevice *dev)
+{
+	int ret;
+
+	ret = device_bind_driver_to_node(dev->parent,
+					 "ti-serdes-am654-mux-clk",
+					 dev_read_name(dev), dev->node,
+					 NULL);
+	if (ret) {
+		dev_err(dev, "%s: not able to bind clock driver\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int serdes_am654_probe(struct udevice *dev)
+{
+	struct serdes_am654 *phy = dev_get_priv(dev);
+	struct power_domain serdes_pwrdmn;
+	struct regmap *serdes_ctl;
+	struct regmap *map;
+	int ret;
+
+	ret = regmap_init_mem(dev_ofnode(dev), &map);
+	if (ret)
+		return ret;
+
+	phy->regmap = map;
+
+	serdes_ctl = syscon_regmap_lookup_by_phandle(dev, "ti,serdes-clk");
+	if (IS_ERR(serdes_ctl)) {
+		dev_err(dev, "unable to find syscon device\n");
+		return PTR_ERR(serdes_ctl);
+	}
+
+	phy->serdes_ctl = serdes_ctl;
+
+	ret = power_domain_get_by_index(dev, &serdes_pwrdmn, 0);
+	if (ret) {
+		dev_err(dev, "failed to get power domain\n");
+		return ret;
+	}
+
+	ret = power_domain_on(&serdes_pwrdmn);
+	if (ret) {
+		dev_err(dev, "Power domain on failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct udevice_id serdes_am654_phy_ids[] = {
+	{
+		.compatible = "ti,phy-am654-serdes",
+	},
+};
+
+static const struct phy_ops serdes_am654_phy_ops = {
+	.reset		= serdes_am654_reset,
+	.init		= serdes_am654_init,
+	.power_on	= serdes_am654_power_on,
+	.power_off	= serdes_am654_power_off,
+	.of_xlate	= serdes_am654_of_xlate,
+};
+
+U_BOOT_DRIVER(am654_serdes_phy) = {
+	.name	= "am654_serdes_phy",
+	.id	= UCLASS_PHY,
+	.of_match = serdes_am654_phy_ids,
+	.bind = serdes_am654_bind,
+	.ops = &serdes_am654_phy_ops,
+	.probe = serdes_am654_probe,
+	.priv_auto_alloc_size = sizeof(struct serdes_am654),
+};

+ 4 - 4
drivers/power/domain/ti-sci-power-domain.c

@@ -68,8 +68,8 @@ static int ti_sci_power_domain_on(struct power_domain *pd)
 		ret = dops->get_device(sci, pd->id);
 
 	if (ret)
-		dev_err(power_domain->dev, "%s: get_device failed (%d)\n",
-			__func__, ret);
+		dev_err(pd->dev, "%s: get_device(%lu) failed (%d)\n",
+			__func__, pd->id, ret);
 
 	return ret;
 }
@@ -85,8 +85,8 @@ static int ti_sci_power_domain_off(struct power_domain *pd)
 
 	ret = dops->put_device(sci, pd->id);
 	if (ret)
-		dev_err(power_domain->dev, "%s: put_device failed (%d)\n",
-			__func__, ret);
+		dev_err(pd->dev, "%s: put_device(%lu) failed (%d)\n",
+			__func__, pd->id, ret);
 
 	return ret;
 }

+ 8 - 1
drivers/watchdog/Kconfig

@@ -28,7 +28,6 @@ config OMAP_WATCHDOG
 	bool "TI OMAP watchdog driver"
 	depends on ARCH_OMAP2PLUS
 	select HW_WATCHDOG
-	default y if AM33XX
 	help
 	  Say Y here to enable the OMAP3+ watchdog driver.
 
@@ -113,6 +112,14 @@ config WDT_MTK
 	  The watchdog timer is stopped when initialized.
 	  It performs full SoC reset.
 
+config WDT_OMAP3
+        bool "TI OMAP watchdog timer support"
+        depends on WDT && ARCH_OMAP2PLUS
+        default y if AM33XX
+        help
+	  This enables OMAP3+ watchdog timer driver, which can be
+	  found on some TI chipsets and inline with driver model.
+
 config WDT_ORION
 	bool "Orion watchdog timer support"
 	depends on WDT

+ 1 - 0
drivers/watchdog/Makefile

@@ -25,6 +25,7 @@ obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
 obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
 obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
 obj-$(CONFIG_WDT_MTK) += mtk_wdt.o
+obj-$(CONFIG_WDT_OMAP3) += omap_wdt.o
 obj-$(CONFIG_WDT_SP805) += sp805_wdt.o
 obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o
 obj-$(CONFIG_WDT_TANGIER) += tangier_wdt.o

+ 121 - 0
drivers/watchdog/omap_wdt.c

@@ -42,10 +42,14 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/arch/cpu.h>
+#include <wdt.h>
+#include <dm.h>
+#include <errno.h>
 
 /* Hardware timeout in seconds */
 #define WDT_HW_TIMEOUT 60
 
+#if !CONFIG_IS_ENABLED(WDT)
 static unsigned int wdt_trgr_pattern = 0x1234;
 
 void hw_watchdog_reset(void)
@@ -134,3 +138,120 @@ void hw_watchdog_init(void)
 	while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR)
 		;
 }
+
+void watchdog_reset(void)
+{
+	hw_watchdog_reset();
+}
+
+#else
+
+static int omap3_wdt_reset(struct udevice *dev)
+{
+	struct omap3_wdt_priv *priv = dev_get_priv(dev);
+
+	priv->wdt_trgr_pattern = 0x1234;
+/*
+ * Somebody just triggered watchdog reset and write to WTGR register
+ * is in progress. It is resetting right now, no need to trigger it
+ * again
+ */
+	if ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WTGR)
+		return 0;
+
+	priv->wdt_trgr_pattern = ~(priv->wdt_trgr_pattern);
+	writel(priv->wdt_trgr_pattern, &priv->regs->wdtwtgr);
+/*
+ * Don't wait for posted write to complete, i.e. don't check
+ * WDT_WWPS_PEND_WTGR bit in WWPS register. There is no writes to
+ * WTGR register outside of this func, and if entering it
+ * we see WDT_WWPS_PEND_WTGR bit set, it means watchdog reset
+ * was just triggered. This prevents us from wasting time in busy
+ * polling of WDT_WWPS_PEND_WTGR bit.
+ */
+	return 0;
+}
+
+static int omap3_wdt_stop(struct udevice *dev)
+{
+	struct omap3_wdt_priv *priv = dev_get_priv(dev);
+
+/* disable watchdog */
+	writel(0xAAAA, &priv->regs->wdtwspr);
+	while (readl(&priv->regs->wdtwwps) != 0x0)
+		;
+	writel(0x5555, &priv->regs->wdtwspr);
+	while (readl(&priv->regs->wdtwwps) != 0x0)
+		;
+	return 0;
+}
+
+static int omap3_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+	struct omap3_wdt_priv *priv = dev_get_priv(dev);
+	u32 pre_margin = GET_WLDR_VAL(timeout_ms);
+/*
+ * Make sure the watchdog is disabled. This is unfortunately required
+ * because writing to various registers with the watchdog running has no
+ * effect.
+ */
+	omap3_wdt_stop(dev);
+
+/* initialize prescaler */
+	while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WCLR)
+		;
+
+	writel(WDT_WCLR_PRE | (PTV << WDT_WCLR_PTV_OFF), &priv->regs->wdtwclr);
+	while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WCLR)
+		;
+/* just count up at 32 KHz */
+	while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WLDR)
+		;
+
+	writel(pre_margin, &priv->regs->wdtwldr);
+	while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WLDR)
+		;
+/* Sequence to enable the watchdog */
+	writel(0xBBBB, &priv->regs->wdtwspr);
+	while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WSPR)
+		;
+
+	writel(0x4444, &priv->regs->wdtwspr);
+	while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WSPR)
+		;
+
+	return 0;
+}
+
+static int omap3_wdt_probe(struct udevice *dev)
+{
+	struct omap3_wdt_priv *priv = dev_get_priv(dev);
+
+	priv->regs = (struct wd_timer *)devfdt_get_addr(dev);
+	if (!priv->regs)
+		return -EINVAL;
+
+	debug("%s: Probing wdt%u\n", __func__, dev->seq);
+	return 0;
+}
+
+static const struct wdt_ops omap3_wdt_ops = {
+	.start = omap3_wdt_start,
+	.stop = omap3_wdt_stop,
+	.reset = omap3_wdt_reset,
+};
+
+static const struct udevice_id omap3_wdt_ids[] = {
+	{ .compatible = "ti,omap3-wdt" },
+	{ }
+};
+
+U_BOOT_DRIVER(omap3_wdt) = {
+	.name = "omap3_wdt",
+	.id = UCLASS_WDT,
+	.of_match = omap3_wdt_ids,
+	.ops = &omap3_wdt_ops,
+	.probe = omap3_wdt_probe,
+	.priv_auto_alloc_size = sizeof(struct omap3_wdt_priv),
+};
+#endif /* !CONFIG_IS_ENABLED(WDT) */

+ 12 - 0
include/clk.h

@@ -333,6 +333,18 @@ int clk_disable(struct clk *clk);
  */
 int clk_disable_bulk(struct clk_bulk *bulk);
 
+/**
+ * clk_is_match - check if two clk's point to the same hardware clock
+ * @p: clk compared against q
+ * @q: clk compared against p
+ *
+ * Returns true if the two struct clk pointers both point to the same hardware
+ * clock node.
+ *
+ * Returns false otherwise. Note that two NULL clks are treated as matching.
+ */
+bool clk_is_match(const struct clk *p, const struct clk *q);
+
 int soc_clk_dump(void);
 
 /**

+ 83 - 0
include/configs/brsmarc1.h

@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * brsmarc1.h
+ *
+ * specific parts for B&R BRSMARC1 Motherboard
+ *
+ * Copyright (C) 2017 Hannes Schmelzer <oe5hpm@oevsv.at> -
+ * B&R Industrial Automation GmbH - http://www.br-automation.com
+ *
+ */
+
+#ifndef __CONFIG_BRSMARC1_H__
+#define __CONFIG_BRSMARC1_H__
+
+#include <configs/bur_cfg_common.h>
+#include <configs/bur_am335x_common.h>
+/* ------------------------------------------------------------------------- */
+#define CONFIG_BOARD_TYPES
+
+/* memory */
+#define CONFIG_SYS_MALLOC_LEN		(5 * 1024 * 1024)
+#define CONFIG_SYS_BOOTM_LEN		(32 * 1024 * 1024)
+
+/* Clock Defines */
+#define V_OSCK				26000000  /* Clock output from T2 */
+#define V_SCLK				(V_OSCK)
+
+#define CONFIG_MACH_TYPE		3589
+
+#ifndef CONFIG_SPL_BUILD
+
+/* Default environment */
+#define CONFIG_EXTRA_ENV_SETTINGS	\
+BUR_COMMON_ENV \
+"autoload=0\0" \
+"scradr=" __stringify(CONFIG_SYS_LOAD_ADDR) "\0" \
+"cfgscr=mw ${dtbaddr} 0;" \
+" sf probe && sf read ${scradr} 0xC0000 0x10000 && source ${scradr};" \
+" fdt addr ${dtbaddr} || cp ${fdtcontroladdr} ${dtbaddr} 4000\0" \
+"dtbaddr=0x84000000\0" \
+"loadaddr=0x82000000\0" \
+"b_break=0\0" \
+"b_tgts_std=mmc0 mmc1 def net usb0\0" \
+"b_tgts_rcy=def net usb0\0" \
+"b_tgts_pme=net usb0 mmc0 mmc1\0" \
+"b_deftgts=if test ${b_mode} = 12; then setenv b_tgts ${b_tgts_pme};" \
+" elif test ${b_mode} = 0; then setenv b_tgts ${b_tgts_rcy};" \
+" else setenv b_tgts ${b_tgts_std}; fi\0" \
+"b_mmc0=load mmc 1 ${scradr} bootscr.img && source ${scradr}\0" \
+"b_mmc1=load mmc 1 ${loadaddr} arimg.ugz && run startsys\0" \
+"b_def=sf read ${loadaddr} 100000 700000; run startsys\0" \
+"b_net=tftp ${scradr} netscript.img && source ${scradr}\0" \
+"b_usb0=usb start && load usb 0 ${scradr} bootscr.img && source ${scradr}\0" \
+"b_default=run b_deftgts; for target in ${b_tgts};"\
+" do run b_${target}; if test ${b_break} = 1; then; exit; fi; done\0" \
+"vxargs=setenv bootargs cpsw(0,0)host:vxWorks h=${serverip}" \
+" e=${ipaddr}:${netmask} g=${gatewayip} u=vxWorksFTP pw=vxWorks\0" \
+"vxfdt=fdt addr ${dtbaddr}; fdt resize 0x8000;" \
+" fdt boardsetup\0" \
+"startsys=run vxargs && mw 0x80001100 0 && run vxfdt &&" \
+" bootm ${loadaddr} - ${dtbaddr}\0"
+#endif /* !CONFIG_SPL_BUILD*/
+
+/* undefine command which we not need here */
+#undef CONFIG_BOOTM_NETBSD
+#undef CONFIG_BOOTM_PLAN9
+#undef CONFIG_BOOTM_RTEMS
+
+/* Support both device trees and ATAGs. */
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+
+/* SPI Flash */
+#define CONFIG_SYS_SPI_U_BOOT_OFFS		0x40000
+
+/* Environment */
+#define CONFIG_SYS_REDUNDAND_ENVIRONMENT
+#define CONFIG_ENV_OFFSET_REDUND		(CONFIG_ENV_OFFSET + \
+						 CONFIG_ENV_SECT_SIZE)
+
+#define CONFIG_CONS_INDEX			1
+#endif	/* __CONFIG_BRSMARC1_H__ */

+ 2 - 2
include/configs/da850evm.h

@@ -26,7 +26,7 @@
 #define CONFIG_SYS_OSCIN_FREQ		24000000
 #define CONFIG_SYS_TIMERBASE		DAVINCI_TIMER0_BASE
 #define CONFIG_SYS_HZ_CLOCK		clk_get(DAVINCI_AUXCLK_CLKID)
-#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_SKIP_LOWLEVEL_INIT_ONLY
 
 #ifdef CONFIG_DIRECT_NOR_BOOT
 #define CONFIG_ARCH_CPU_INIT
@@ -192,7 +192,7 @@
 #ifdef CONFIG_USE_NOR
 #define CONFIG_SYS_MAX_FLASH_BANKS	1 /* max number of flash banks */
 #define CONFIG_SYS_FLASH_SECT_SZ	(128 << 10) /* 128KB */
-#define CONFIG_ENV_OFFSET		(CONFIG_SYS_FLASH_SECT_SZ * 3)
+#define CONFIG_ENV_OFFSET		(SZ_1M)
 #define CONFIG_ENV_SIZE			(10 << 10) /* 10KB */
 #define CONFIG_SYS_FLASH_BASE		DAVINCI_ASYNC_EMIF_DATA_CE2_BASE
 #define PHYS_FLASH_SIZE			(8 << 20) /* Flash size 8MB */

+ 18 - 0
include/dm/fdtaddr.h

@@ -120,4 +120,22 @@ fdt_addr_t devfdt_get_addr_size_index(struct udevice *dev, int index,
  */
 fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name);
 
+/**
+ * devfdt_get_addr_size_name() - Get the reg property and its size for a device,
+ *				 indexed by name
+ *
+ * Returns the address and size specified in the 'reg' property of a device.
+ *
+ * @dev: Pointer to a device
+ * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
+ *	  'reg-names' property providing named-based identification. @index
+ *	  indicates the value to search for in 'reg-names'.
+ * @size: Pointer to size variable - this function returns the size
+ *        specified in the 'reg' property here
+ *
+ * @return addr
+ */
+fdt_addr_t devfdt_get_addr_size_name(struct udevice *dev, const char *name,
+				     fdt_size_t *size);
+
 #endif

+ 41 - 0
include/dm/read.h

@@ -144,6 +144,19 @@ int dev_read_size(struct udevice *dev, const char *propname);
  */
 fdt_addr_t dev_read_addr_index(struct udevice *dev, int index);
 
+/**
+ * dev_read_addr_size_index() - Get the indexed reg property of a device
+ *
+ * @dev: Device to read from
+ * @index: the 'reg' property can hold a list of <addr, size> pairs
+ *	   and @index is used to select which one is required
+ * @size: place to put size value (on success)
+ *
+ * @return address or FDT_ADDR_T_NONE if not found
+ */
+fdt_addr_t dev_read_addr_size_index(struct udevice *dev, int index,
+				    fdt_size_t *size);
+
 /**
  * dev_remap_addr_index() - Get the indexed reg property of a device
  *                               as a memory-mapped I/O pointer
@@ -168,6 +181,20 @@ void *dev_remap_addr_index(struct udevice *dev, int index);
  */
 fdt_addr_t dev_read_addr_name(struct udevice *dev, const char* name);
 
+/**
+ * dev_read_addr_size_name() - Get the reg property of a device, indexed by name
+ *
+ * @dev: Device to read from
+ * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
+ *	  'reg-names' property providing named-based identification. @index
+ *	  indicates the value to search for in 'reg-names'.
+ *  @size: place to put size value (on success)
+ *
+ * @return address or FDT_ADDR_T_NONE if not found
+ */
+fdt_addr_t dev_read_addr_size_name(struct udevice *dev, const char *name,
+				   fdt_size_t *size);
+
 /**
  * dev_remap_addr_name() - Get the reg property of a device, indexed by name,
  *                         as a memory-mapped I/O pointer
@@ -601,12 +628,26 @@ static inline fdt_addr_t dev_read_addr_index(struct udevice *dev, int index)
 	return devfdt_get_addr_index(dev, index);
 }
 
+static inline fdt_addr_t dev_read_addr_size_index(struct udevice *dev,
+						  int index,
+						  fdt_size_t *size)
+{
+	return devfdt_get_addr_size_index(dev, index, size);
+}
+
 static inline fdt_addr_t dev_read_addr_name(struct udevice *dev,
 					    const char *name)
 {
 	return devfdt_get_addr_name(dev, name);
 }
 
+static inline fdt_addr_t dev_read_addr_size_name(struct udevice *dev,
+						 const char *name,
+						 fdt_size_t *size)
+{
+	return devfdt_get_addr_size_name(dev, name, size);
+}
+
 static inline fdt_addr_t dev_read_addr(struct udevice *dev)
 {
 	return devfdt_get_addr(dev);

+ 13 - 0
include/dt-bindings/phy/phy-am654-serdes.h

@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides constants for AM654 SERDES.
+ */
+
+#ifndef _DT_BINDINGS_AM654_SERDES
+#define _DT_BINDINGS_AM654_SERDES
+
+#define AM654_SERDES_CMU_REFCLK	0
+#define AM654_SERDES_LO_REFCLK	1
+#define AM654_SERDES_RO_REFCLK	2
+
+#endif /* _DT_BINDINGS_AM654_SERDES */

+ 1 - 1
include/watchdog.h

@@ -77,7 +77,7 @@ int init_func_watchdog_reset(void);
  * Prototypes from $(CPU)/cpu.c.
  */
 
-#if defined(CONFIG_HW_WATCHDOG) && !defined(__ASSEMBLY__)
+#if (defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)) && !defined(__ASSEMBLY__)
 	void hw_watchdog_init(void);
 #endif
 

+ 1 - 0
test/dm/clk.c

@@ -24,6 +24,7 @@ static int dm_test_clk_base(struct unit_test_state *uts)
 	/* Get the same clk port in 2 different ways and compare */
 	ut_assertok(clk_get_by_index(dev, 1, &clk_method1));
 	ut_assertok(clk_get_by_index_nodev(dev_ofnode(dev), 1, &clk_method2));
+	ut_asserteq(clk_is_match(&clk_method1, &clk_method2), true);
 	ut_asserteq(clk_method1.id, clk_method2.id);
 
 	return 0;

+ 12 - 4
test/dm/test-fdt.c

@@ -549,12 +549,14 @@ static int dm_test_fdt_remap_addr_index_flat(struct unit_test_state *uts)
 {
 	struct udevice *dev;
 	fdt_addr_t addr;
+	fdt_size_t size;
 	void *paddr;
 
 	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev));
 
-	addr = devfdt_get_addr_index(dev, 0);
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
 	ut_asserteq(0x8000, addr);
+	ut_asserteq(0x1000, size);
 
 	paddr = map_physmem(addr, 0, MAP_NOCACHE);
 	ut_assertnonnull(paddr);
@@ -569,12 +571,14 @@ static int dm_test_fdt_remap_addr_name_flat(struct unit_test_state *uts)
 {
 	struct udevice *dev;
 	fdt_addr_t addr;
+	fdt_size_t size;
 	void *paddr;
 
 	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev));
 
-	addr = devfdt_get_addr_name(dev, "sandbox-dummy-0");
+	addr = devfdt_get_addr_size_name(dev, "sandbox-dummy-0", &size);
 	ut_asserteq(0x8000, addr);
+	ut_asserteq(0x1000, size);
 
 	paddr = map_physmem(addr, 0, MAP_NOCACHE);
 	ut_assertnonnull(paddr);
@@ -609,12 +613,14 @@ static int dm_test_fdt_remap_addr_index_live(struct unit_test_state *uts)
 {
 	struct udevice *dev;
 	fdt_addr_t addr;
+	fdt_size_t size;
 	void *paddr;
 
 	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev));
 
-	addr = dev_read_addr_index(dev, 0);
+	addr = dev_read_addr_size_index(dev, 0, &size);
 	ut_asserteq(0x8000, addr);
+	ut_asserteq(0x1000, size);
 
 	paddr = map_physmem(addr, 0, MAP_NOCACHE);
 	ut_assertnonnull(paddr);
@@ -629,12 +635,14 @@ static int dm_test_fdt_remap_addr_name_live(struct unit_test_state *uts)
 {
 	struct udevice *dev;
 	fdt_addr_t addr;
+	fdt_size_t size;
 	void *paddr;
 
 	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev));
 
-	addr = dev_read_addr_name(dev, "sandbox-dummy-0");
+	addr = dev_read_addr_size_name(dev, "sandbox-dummy-0", &size);
 	ut_asserteq(0x8000, addr);
+	ut_asserteq(0x1000, size);
 
 	paddr = map_physmem(addr, 0, MAP_NOCACHE);
 	ut_assertnonnull(paddr);