Browse Source

Merge branch '2021-07-14-platform-updates'

- Assorted platform updates
Tom Rini 2 years ago
parent
commit
eae8c7c338
41 changed files with 1682 additions and 254 deletions
  1. 2 2
      MAINTAINERS
  2. 1 0
      arch/arm/dts/Makefile
  3. 189 0
      arch/arm/dts/uniphier-ld20-akebi96.dts
  4. 1 2
      arch/arm/mach-snapdragon/pinctrl-apq8016.c
  5. 1 1
      arch/arm/mach-snapdragon/pinctrl-apq8096.c
  6. 2 0
      arch/arm/mach-u8500/Kconfig
  7. 1 0
      board/ste/stemmy/README
  8. 148 1
      board/ste/stemmy/stemmy.c
  9. 7 3
      common/board_info.c
  10. 1 1
      configs/stemmy_defconfig
  11. 1 2
      configs/total_compute_defconfig
  12. 2 1
      doc/git-mailrc
  13. 2 0
      drivers/Kconfig
  14. 1 0
      drivers/Makefile
  15. 3 0
      drivers/clk/uniphier/clk-uniphier-sys.c
  16. 8 0
      drivers/gpio/Kconfig
  17. 1 1
      drivers/gpio/Makefile
  18. 0 221
      drivers/gpio/db8500_gpio.c
  19. 125 0
      drivers/gpio/nmk_gpio.c
  20. 1 0
      drivers/misc/i2c_eeprom.c
  21. 10 0
      drivers/pci/Kconfig
  22. 1 0
      drivers/pci/Makefile
  23. 424 0
      drivers/pci/pcie_uniphier.c
  24. 6 0
      drivers/phy/Kconfig
  25. 1 0
      drivers/phy/Makefile
  26. 52 0
      drivers/phy/phy-ab8500-usb.c
  27. 12 0
      drivers/phy/socionext/Kconfig
  28. 6 0
      drivers/phy/socionext/Makefile
  29. 59 0
      drivers/phy/socionext/phy-uniphier-pcie.c
  30. 10 0
      drivers/power/pmic/Kconfig
  31. 1 0
      drivers/power/pmic/Makefile
  32. 268 0
      drivers/power/pmic/ab8500.c
  33. 3 0
      drivers/reset/reset-uniphier.c
  34. 2 5
      drivers/timer/nomadik-mtu-timer.c
  35. 10 1
      drivers/usb/musb-new/Kconfig
  36. 1 0
      drivers/usb/musb-new/Makefile
  37. 1 1
      drivers/usb/musb-new/musb_core.c
  38. 179 0
      drivers/usb/musb-new/ux500.c
  39. 12 12
      include/configs/stemmy.h
  40. 2 0
      include/configs/uniphier.h
  41. 125 0
      include/power/ab8500.h

+ 2 - 2
MAINTAINERS

@@ -118,8 +118,8 @@ F:	cmd/arm/
 ARM ALTERA SOCFPGA
 ARM ALTERA SOCFPGA
 M:	Marek Vasut <marex@denx.de>
 M:	Marek Vasut <marex@denx.de>
 M:	Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
 M:	Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
-M:	Ley Foon Tan <lftan.linux@gmail.com>
-S:	Maintainted
+M:	Tien Fong Chee <tien.fong.chee@intel.com>
+S:	Maintained
 T:	git https://source.denx.de/u-boot/custodians/u-boot-socfpga.git
 T:	git https://source.denx.de/u-boot/custodians/u-boot-socfpga.git
 F:	arch/arm/mach-socfpga/
 F:	arch/arm/mach-socfpga/
 F:	drivers/sysreset/sysreset_socfpga*
 F:	drivers/sysreset/sysreset_socfpga*

+ 1 - 0
arch/arm/dts/Makefile

@@ -254,6 +254,7 @@ dtb-$(CONFIG_ARCH_UNIPHIER_LD11) += \
 	uniphier-ld11-global.dtb \
 	uniphier-ld11-global.dtb \
 	uniphier-ld11-ref.dtb
 	uniphier-ld11-ref.dtb
 dtb-$(CONFIG_ARCH_UNIPHIER_LD20) += \
 dtb-$(CONFIG_ARCH_UNIPHIER_LD20) += \
+	uniphier-ld20-akebi96.dtb \
 	uniphier-ld20-global.dtb \
 	uniphier-ld20-global.dtb \
 	uniphier-ld20-ref.dtb
 	uniphier-ld20-ref.dtb
 dtb-$(CONFIG_ARCH_UNIPHIER_LD4) += \
 dtb-$(CONFIG_ARCH_UNIPHIER_LD4) += \

+ 189 - 0
arch/arm/dts/uniphier-ld20-akebi96.dts

@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+//
+// Device Tree Source for Akebi96 Development Board
+//
+// Derived from uniphier-ld20-global.dts.
+//
+// Copyright (C) 2015-2017 Socionext Inc.
+// Copyright (C) 2019-2020 Linaro Ltd.
+
+/dts-v1/;
+#include <dt-bindings/gpio/uniphier-gpio.h>
+#include "uniphier-ld20.dtsi"
+
+/ {
+	model = "Akebi96";
+	compatible = "socionext,uniphier-ld20-akebi96",
+		     "socionext,uniphier-ld20";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
+		spi3 = &spi3;
+		ethernet0 = &eth;
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0 0x80000000 0 0xc0000000>;
+	};
+
+	framebuffer@c0000000 {
+		compatible = "simple-framebuffer";
+		reg = <0 0xc0000000 0 0x02000000>;
+		width = <1920>;
+		height = <1080>;
+		stride = <7680>;
+		format = "a8r8g8b8";
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		memory@c0000000 {
+			reg = <0 0xc0000000 0 0x02000000>;
+			no-map;
+		};
+	};
+
+	sound {
+		compatible = "audio-graph-card";
+		label = "UniPhier LD20";
+		dais = <&spdif_port0
+			&comp_spdif_port0>;
+	};
+
+	spdif-out {
+		compatible = "linux,spdif-dit";
+		#sound-dai-cells = <0>;
+
+		port@0 {
+			spdif_tx: endpoint {
+				remote-endpoint = <&spdif_hiecout1>;
+			};
+		};
+	};
+
+	comp-spdif-out {
+		compatible = "linux,spdif-dit";
+		#sound-dai-cells = <0>;
+
+		port@0 {
+			comp_spdif_tx: endpoint {
+				remote-endpoint = <&comp_spdif_hiecout1>;
+			};
+		};
+	};
+
+	firmware {
+		optee {
+			compatible = "linaro,optee-tz";
+			method = "smc";
+		};
+	};
+};
+
+&spi3 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	usb-over-spi@0 {
+		compatible = "maxim,max3421-udc";
+		reg = <0>;
+		spi-max-frequency = <12500000>;
+		interrupt-parent = <&gpio>;
+		interrupt-names = "udc";
+		interrupts = <0 2>;
+	};
+};
+
+&serial0 {
+	/* Onboard USB-UART */
+	status = "okay";
+};
+
+&serial2 {
+	/* LS connector UART1 */
+	status = "okay";
+};
+
+&serial3 {
+	/* LS connector UART0 */
+	status = "okay";
+};
+
+&spdif_hiecout1 {
+	remote-endpoint = <&spdif_tx>;
+};
+
+&comp_spdif_hiecout1 {
+	remote-endpoint = <&comp_spdif_tx>;
+};
+
+&i2c0 {
+	/* LS connector I2C0 */
+	status = "okay";
+};
+
+&i2c1 {
+	/* LS connector I2C1 */
+	status = "okay";
+};
+
+&eth {
+	status = "okay";
+	phy-handle = <&ethphy>;
+};
+
+&mdio {
+	ethphy: ethernet-phy@0 {
+		reg = <0>;
+	};
+};
+
+&usb {
+	status = "okay";
+};
+
+&pcie {
+	status = "okay";
+};
+
+&gpio {
+	/* IRQs for Max3421 */
+	xirq0 {
+		gpio-hog;
+		gpios = <UNIPHIER_GPIO_IRQ(0) 1>;
+		input;
+	};
+	xirq10 {
+		gpio-hog;
+		gpios = <UNIPHIER_GPIO_IRQ(10) 1>;
+		input;
+	};
+};
+
+&pinctrl_aout1 {
+	groups = "aout1b";
+};
+
+&pinctrl_uart3 {
+	groups = "uart3", "uart3_ctsrts";
+};

+ 1 - 2
arch/arm/mach-snapdragon/pinctrl-apq8016.c

@@ -10,7 +10,7 @@
 #include <common.h>
 #include <common.h>
 
 
 #define MAX_PIN_NAME_LEN 32
 #define MAX_PIN_NAME_LEN 32
-static char pin_name[MAX_PIN_NAME_LEN];
+static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
 static const char * const msm_pinctrl_pins[] = {
 static const char * const msm_pinctrl_pins[] = {
 	"SDC1_CLK",
 	"SDC1_CLK",
 	"SDC1_CMD",
 	"SDC1_CMD",
@@ -59,4 +59,3 @@ struct msm_pinctrl_data apq8016_data = {
 	.get_function_mux = apq8016_get_function_mux,
 	.get_function_mux = apq8016_get_function_mux,
 	.get_pin_name = apq8016_get_pin_name,
 	.get_pin_name = apq8016_get_pin_name,
 };
 };
-

+ 1 - 1
arch/arm/mach-snapdragon/pinctrl-apq8096.c

@@ -10,7 +10,7 @@
 #include <common.h>
 #include <common.h>
 
 
 #define MAX_PIN_NAME_LEN 32
 #define MAX_PIN_NAME_LEN 32
-static char pin_name[MAX_PIN_NAME_LEN];
+static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
 static const char * const msm_pinctrl_pins[] = {
 static const char * const msm_pinctrl_pins[] = {
 	"SDC1_CLK",
 	"SDC1_CLK",
 	"SDC1_CMD",
 	"SDC1_CMD",

+ 2 - 0
arch/arm/mach-u8500/Kconfig

@@ -8,6 +8,7 @@ choice
 
 
 config TARGET_STEMMY
 config TARGET_STEMMY
 	bool "Samsung (stemmy) board"
 	bool "Samsung (stemmy) board"
+	select MISC_INIT_R
 	help
 	help
 	  The Samsung "stemmy" board supports Samsung smartphones released with
 	  The Samsung "stemmy" board supports Samsung smartphones released with
 	  the ST-Ericsson NovaThor U8500 SoC, e.g.
 	  the ST-Ericsson NovaThor U8500 SoC, e.g.
@@ -15,6 +16,7 @@ config TARGET_STEMMY
 	      - Samsung Galaxy S III mini (GT-I8190)	"golden"
 	      - Samsung Galaxy S III mini (GT-I8190)	"golden"
 	      - Samsung Galaxy S Advance (GT-I9070)	"janice"
 	      - Samsung Galaxy S Advance (GT-I9070)	"janice"
 	      - Samsung Galaxy Xcover 2 (GT-S7710)	"skomer"
 	      - Samsung Galaxy Xcover 2 (GT-S7710)	"skomer"
+	      - Samsung Galaxy Ace 2 (GT-I8160)		"codina"
 
 
 	  and likely others as well (untested).
 	  and likely others as well (untested).
 
 

+ 1 - 0
board/ste/stemmy/README

@@ -7,6 +7,7 @@ the ST-Ericsson NovaThor U8500 SoC, e.g.
 	- Samsung Galaxy S III mini (GT-I8190)	"golden"
 	- Samsung Galaxy S III mini (GT-I8190)	"golden"
 	- Samsung Galaxy S Advance (GT-I9070)	"janice"
 	- Samsung Galaxy S Advance (GT-I9070)	"janice"
 	- Samsung Galaxy Xcover 2 (GT-S7710)	"skomer"
 	- Samsung Galaxy Xcover 2 (GT-S7710)	"skomer"
+	- Samsung Galaxy Ace 2 (GT-I8160)	"codina"
 
 
 and likely others as well (untested).
 and likely others as well (untested).
 
 

+ 148 - 1
board/ste/stemmy/stemmy.c

@@ -3,18 +3,165 @@
  * Copyright (C) 2019 Stephan Gerhold <stephan@gerhold.net>
  * Copyright (C) 2019 Stephan Gerhold <stephan@gerhold.net>
  */
  */
 #include <common.h>
 #include <common.h>
+#include <env.h>
 #include <init.h>
 #include <init.h>
+#include <log.h>
+#include <stdlib.h>
 #include <asm/global_data.h>
 #include <asm/global_data.h>
+#include <asm/setup.h>
+#include <asm/system.h>
 
 
 DECLARE_GLOBAL_DATA_PTR;
 DECLARE_GLOBAL_DATA_PTR;
 
 
+/* Parse atags provided by Samsung bootloader to get available memory */
+static ulong fw_mach __section(".data");
+static ulong fw_atags __section(".data");
+
+static const struct tag *fw_atags_copy;
+static uint fw_atags_size;
+
+void save_boot_params(ulong r0, ulong r1, ulong r2, ulong r3)
+{
+	fw_mach = r1;
+	fw_atags = r2;
+	save_boot_params_ret();
+}
+
+static const struct tag *fw_atags_get(void)
+{
+	const struct tag *tags = (const struct tag *)fw_atags;
+
+	if (tags->hdr.tag != ATAG_CORE) {
+		log_err("Invalid atags: tag 0x%x at %p\n", tags->hdr.tag, tags);
+		return NULL;
+	}
+
+	return tags;
+}
+
 int dram_init(void)
 int dram_init(void)
 {
 {
-	gd->ram_size = get_ram_size(CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_SDRAM_SIZE);
+	const struct tag *t, *tags = fw_atags_get();
+
+	if (!tags)
+		return -EINVAL;
+
+	for_each_tag(t, tags) {
+		if (t->hdr.tag != ATAG_MEM)
+			continue;
+
+		debug("Memory: %#x-%#x (size %#x)\n", t->u.mem.start,
+		      t->u.mem.start + t->u.mem.size, t->u.mem.size);
+		gd->ram_size += t->u.mem.size;
+	}
+	return 0;
+}
+
+int dram_init_banksize(void)
+{
+	const struct tag *t, *tags = fw_atags_get();
+	unsigned int bank = 0;
+
+	if (!tags)
+		return -EINVAL;
+
+	for_each_tag(t, tags) {
+		if (t->hdr.tag != ATAG_MEM)
+			continue;
+
+		gd->bd->bi_dram[bank].start = t->u.mem.start;
+		gd->bd->bi_dram[bank].size = t->u.mem.size;
+		if (++bank == CONFIG_NR_DRAM_BANKS)
+			break;
+	}
 	return 0;
 	return 0;
 }
 }
 
 
 int board_init(void)
 int board_init(void)
 {
 {
+	gd->bd->bi_arch_number = fw_mach;
+	gd->bd->bi_boot_params = fw_atags;
 	return 0;
 	return 0;
 }
 }
+
+static void parse_serial(const struct tag_serialnr *serialnr)
+{
+	char serial[17];
+
+	if (env_get("serial#"))
+		return;
+
+	sprintf(serial, "%08x%08x", serialnr->high, serialnr->low);
+	env_set("serial#", serial);
+}
+
+/*
+ * The downstream/vendor kernel (provided by Samsung) uses ATAGS for booting.
+ * It also requires an extremely long cmdline provided by the primary bootloader
+ * that is not suitable for booting mainline.
+ *
+ * Since downstream is the only user of ATAGS, we emulate the behavior of the
+ * Samsung bootloader by generating only the initrd atag in U-Boot, and copying
+ * all other ATAGS as-is from the primary bootloader.
+ */
+static inline bool skip_atag(u32 tag)
+{
+	return (tag == ATAG_NONE || tag == ATAG_CORE ||
+		tag == ATAG_INITRD || tag == ATAG_INITRD2);
+}
+
+static void copy_atags(const struct tag *tags)
+{
+	const struct tag *t;
+	struct tag *copy;
+
+	if (!tags)
+		return;
+
+	/* Calculate necessary size for tags we want to copy */
+	for_each_tag(t, tags) {
+		if (skip_atag(t->hdr.tag))
+			continue;
+
+		if (t->hdr.tag == ATAG_SERIAL)
+			parse_serial(&t->u.serialnr);
+
+		fw_atags_size += t->hdr.size * sizeof(u32);
+	}
+
+	if (!fw_atags_size)
+		return;  /* No tags to copy */
+
+	copy = malloc(fw_atags_size);
+	if (!copy)
+		return;
+	fw_atags_copy = copy;
+
+	/* Copy tags */
+	for_each_tag(t, tags) {
+		if (skip_atag(t->hdr.tag))
+			continue;
+
+		memcpy(copy, t, t->hdr.size * sizeof(u32));
+		copy = tag_next(copy);
+	}
+}
+
+int misc_init_r(void)
+{
+	copy_atags(fw_atags_get());
+	return 0;
+}
+
+void setup_board_tags(struct tag **in_params)
+{
+	if (!fw_atags_copy)
+		return;
+
+	/*
+	 * fw_atags_copy contains only full "struct tag" (plus data)
+	 * so copying it bytewise here should be fine.
+	 */
+	memcpy(*in_params, fw_atags_copy, fw_atags_size);
+	*(u8 **)in_params += fw_atags_size;
+}

+ 7 - 3
common/board_info.c

@@ -31,11 +31,15 @@ int __weak show_board_info(void)
 
 
 		if (IS_ENABLED(CONFIG_SYSINFO)) {
 		if (IS_ENABLED(CONFIG_SYSINFO)) {
 			/* This might provide more detail */
 			/* This might provide more detail */
-			ret = uclass_first_device_err(UCLASS_SYSINFO, &dev);
-			if (!ret)
-				ret = sysinfo_get_str(dev,
+			ret = sysinfo_get(&dev);
+			if (!ret) {
+				ret = sysinfo_detect(dev);
+				if (!ret) {
+					ret = sysinfo_get_str(dev,
 						      SYSINFO_ID_BOARD_MODEL,
 						      SYSINFO_ID_BOARD_MODEL,
 						      sizeof(str), str);
 						      sizeof(str), str);
+				}
+			}
 		}
 		}
 
 
 		/* Fail back to the main 'model' if available */
 		/* Fail back to the main 'model' if available */

+ 1 - 1
configs/stemmy_defconfig

@@ -1,7 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARM=y
 CONFIG_ARCH_U8500=y
 CONFIG_ARCH_U8500=y
 CONFIG_SYS_TEXT_BASE=0x100000
 CONFIG_SYS_TEXT_BASE=0x100000
-CONFIG_NR_DRAM_BANKS=1
+CONFIG_NR_DRAM_BANKS=2
 CONFIG_DEFAULT_DEVICE_TREE="ste-ux500-samsung-stemmy"
 CONFIG_DEFAULT_DEVICE_TREE="ste-ux500-samsung-stemmy"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_HUSH_PARSER=y
 CONFIG_HUSH_PARSER=y

+ 1 - 2
configs/total_compute_defconfig

@@ -13,8 +13,7 @@ CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_BOOTDELAY=5
 CONFIG_BOOTDELAY=5
-CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyAMA0 debug user_debug=31 earlycon=pl011,0x7ff80000 loglevel=9 androidboot.hardware=total_compute video=640x480-32@60 androidboot.boot_devices=1c050000.mmci ip=dhcp androidboot.selinux=permissive"
+# CONFIG_USE_BOOTARGS is not set
 # CONFIG_USE_BOOTCOMMAND is not set
 # CONFIG_USE_BOOTCOMMAND is not set
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set

+ 2 - 1
doc/git-mailrc

@@ -46,6 +46,7 @@ alias simongoldschmidt Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
 alias sjg            Simon Glass <sjg@chromium.org>
 alias sjg            Simon Glass <sjg@chromium.org>
 alias smcnutt        Scott McNutt <smcnutt@psyent.com>
 alias smcnutt        Scott McNutt <smcnutt@psyent.com>
 alias stroese        Stefan Roese <sr@denx.de>
 alias stroese        Stefan Roese <sr@denx.de>
+alias tienfong       Tien Fong Chee <tien.fong.chee@intel.com>
 alias trini          Tom Rini <trini@konsulko.com>
 alias trini          Tom Rini <trini@konsulko.com>
 alias wd             Wolfgang Denk <wd@denx.de>
 alias wd             Wolfgang Denk <wd@denx.de>
 alias priyankajain   Priyanka Jain <priyanka.jain@nxp.com>
 alias priyankajain   Priyanka Jain <priyanka.jain@nxp.com>
@@ -69,7 +70,7 @@ alias s3c            samsung
 alias s5pc           samsung
 alias s5pc           samsung
 alias samsung        uboot, prom
 alias samsung        uboot, prom
 alias snapdragon     uboot, mateusz
 alias snapdragon     uboot, mateusz
-alias socfpga        uboot, marex, dinh, simongoldschmidt, leyfoon
+alias socfpga        uboot, marex, dinh, simongoldschmidt, tienfong
 alias sunxi          uboot, jagan, apritzel
 alias sunxi          uboot, jagan, apritzel
 alias tegra          uboot, sjg, Tom Warren <twarren@nvidia.com>, Stephen Warren <swarren@nvidia.com>
 alias tegra          uboot, sjg, Tom Warren <twarren@nvidia.com>, Stephen Warren <swarren@nvidia.com>
 alias tegra2         tegra
 alias tegra2         tegra

+ 2 - 0
drivers/Kconfig

@@ -80,6 +80,8 @@ source "drivers/phy/allwinner/Kconfig"
 
 
 source "drivers/phy/marvell/Kconfig"
 source "drivers/phy/marvell/Kconfig"
 
 
+source "drivers/phy/socionext/Kconfig"
+
 source "drivers/pinctrl/Kconfig"
 source "drivers/pinctrl/Kconfig"
 
 
 source "drivers/power/Kconfig"
 source "drivers/power/Kconfig"

+ 1 - 0
drivers/Makefile

@@ -96,6 +96,7 @@ obj-$(CONFIG_PCH) += pch/
 obj-y += phy/allwinner/
 obj-y += phy/allwinner/
 obj-y += phy/marvell/
 obj-y += phy/marvell/
 obj-y += phy/rockchip/
 obj-y += phy/rockchip/
+obj-y += phy/socionext/
 obj-y += rtc/
 obj-y += rtc/
 obj-y += scsi/
 obj-y += scsi/
 obj-y += sound/
 obj-y += sound/

+ 3 - 0
drivers/clk/uniphier/clk-uniphier-sys.c

@@ -29,6 +29,7 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = {
 	UNIPHIER_CLK_GATE_SIMPLE(15, 0x2104, 17),	/* usb31 (Pro4, Pro5, PXs2) */
 	UNIPHIER_CLK_GATE_SIMPLE(15, 0x2104, 17),	/* usb31 (Pro4, Pro5, PXs2) */
 	UNIPHIER_CLK_GATE_SIMPLE(16, 0x2104, 19),	/* usb30-phy (PXs2) */
 	UNIPHIER_CLK_GATE_SIMPLE(16, 0x2104, 19),	/* usb30-phy (PXs2) */
 	UNIPHIER_CLK_GATE_SIMPLE(20, 0x2104, 20),	/* usb31-phy (PXs2) */
 	UNIPHIER_CLK_GATE_SIMPLE(20, 0x2104, 20),	/* usb31-phy (PXs2) */
+	UNIPHIER_CLK_GATE_SIMPLE(24, 0x2108, 2),	/* pcie (Pro5) */
 	{ /* sentinel */ }
 	{ /* sentinel */ }
 #endif
 #endif
 };
 };
@@ -43,6 +44,7 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
 	UNIPHIER_CLK_GATE_SIMPLE(14, 0x210c, 14),	/* usb30 (LD20) */
 	UNIPHIER_CLK_GATE_SIMPLE(14, 0x210c, 14),	/* usb30 (LD20) */
 	UNIPHIER_CLK_GATE_SIMPLE(16, 0x210c, 12),	/* usb30-phy0 (LD20) */
 	UNIPHIER_CLK_GATE_SIMPLE(16, 0x210c, 12),	/* usb30-phy0 (LD20) */
 	UNIPHIER_CLK_GATE_SIMPLE(17, 0x210c, 13),	/* usb30-phy1 (LD20) */
 	UNIPHIER_CLK_GATE_SIMPLE(17, 0x210c, 13),	/* usb30-phy1 (LD20) */
+	UNIPHIER_CLK_GATE_SIMPLE(24, 0x210c, 4),	/* pcie */
 	{ /* sentinel */ }
 	{ /* sentinel */ }
 #endif
 #endif
 };
 };
@@ -62,6 +64,7 @@ const struct uniphier_clk_data uniphier_pxs3_sys_clk_data[] = {
 	UNIPHIER_CLK_GATE_SIMPLE(18, 0x210c, 20),	/* usb30-phy2 */
 	UNIPHIER_CLK_GATE_SIMPLE(18, 0x210c, 20),	/* usb30-phy2 */
 	UNIPHIER_CLK_GATE_SIMPLE(20, 0x210c, 17),	/* usb31-phy0 */
 	UNIPHIER_CLK_GATE_SIMPLE(20, 0x210c, 17),	/* usb31-phy0 */
 	UNIPHIER_CLK_GATE_SIMPLE(21, 0x210c, 19),	/* usb31-phy1 */
 	UNIPHIER_CLK_GATE_SIMPLE(21, 0x210c, 19),	/* usb31-phy1 */
+	UNIPHIER_CLK_GATE_SIMPLE(24, 0x210c, 3),	/* pcie */
 	{ /* sentinel */ }
 	{ /* sentinel */ }
 #endif
 #endif
 };
 };

+ 8 - 0
drivers/gpio/Kconfig

@@ -495,4 +495,12 @@ config NX_GPIO
 	  The GPIOs for a device are defined in the device tree with one node
 	  The GPIOs for a device are defined in the device tree with one node
 	  for each bank.
 	  for each bank.
 
 
+config NOMADIK_GPIO
+	bool "Nomadik GPIO driver"
+	depends on DM_GPIO
+	help
+	  Support GPIO access on ST-Ericsson Ux500 SoCs. The GPIOs are arranged
+	  into a number of banks each with 32 GPIOs. The GPIOs for a device are
+	  defined in the device tree with one node for each bank.
+
 endmenu
 endmenu

+ 1 - 1
drivers/gpio/Makefile

@@ -43,7 +43,6 @@ obj-$(CONFIG_MPC8XXX_GPIO)	+= mpc8xxx_gpio.o
 obj-$(CONFIG_MPC83XX_SPISEL_BOOT)	+= mpc83xx_spisel_boot.o
 obj-$(CONFIG_MPC83XX_SPISEL_BOOT)	+= mpc83xx_spisel_boot.o
 obj-$(CONFIG_SH_GPIO_PFC)	+= sh_pfc.o
 obj-$(CONFIG_SH_GPIO_PFC)	+= sh_pfc.o
 obj-$(CONFIG_OMAP_GPIO)	+= omap_gpio.o
 obj-$(CONFIG_OMAP_GPIO)	+= omap_gpio.o
-obj-$(CONFIG_DB8500_GPIO)	+= db8500_gpio.o
 obj-$(CONFIG_BCM2835_GPIO)	+= bcm2835_gpio.o
 obj-$(CONFIG_BCM2835_GPIO)	+= bcm2835_gpio.o
 obj-$(CONFIG_XILINX_GPIO)	+= xilinx_gpio.o
 obj-$(CONFIG_XILINX_GPIO)	+= xilinx_gpio.o
 obj-$(CONFIG_ADI_GPIO2)	+= adi_gpio2.o
 obj-$(CONFIG_ADI_GPIO2)	+= adi_gpio2.o
@@ -68,3 +67,4 @@ obj-$(CONFIG_MT7621_GPIO)	+= mt7621_gpio.o
 obj-$(CONFIG_MSCC_SGPIO)	+= mscc_sgpio.o
 obj-$(CONFIG_MSCC_SGPIO)	+= mscc_sgpio.o
 obj-$(CONFIG_NX_GPIO)		+= nx_gpio.o
 obj-$(CONFIG_NX_GPIO)		+= nx_gpio.o
 obj-$(CONFIG_SIFIVE_GPIO)	+= sifive-gpio.o
 obj-$(CONFIG_SIFIVE_GPIO)	+= sifive-gpio.o
+obj-$(CONFIG_NOMADIK_GPIO)	+= nmk_gpio.o

+ 0 - 221
drivers/gpio/db8500_gpio.c

@@ -1,221 +0,0 @@
-/*
- * Code ported from Nomadik GPIO driver in ST-Ericsson Linux kernel code.
- * The purpose is that GPIO config found in kernel should work by simply
- * copy-paste it to U-Boot.
- *
- * Original Linux authors:
- * Copyright (C) 2008,2009 STMicroelectronics
- * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
- *   Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
- *
- * Ported to U-Boot by:
- * Copyright (C) 2010 Joakim Axelsson <joakim.axelsson AT stericsson.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <common.h>
-#include <asm/io.h>
-
-#include <asm/arch/db8500_gpio.h>
-#include <asm/arch/db8500_pincfg.h>
-#include <linux/compiler.h>
-
-#define IO_ADDR(x) (void *) (x)
-
-/*
- * The GPIO module in the db8500 Systems-on-Chip is an
- * AMBA device, managing 32 pins and alternate functions. The logic block
- * is currently only used in the db8500.
- */
-
-#define GPIO_TOTAL_PINS		268
-#define GPIO_PINS_PER_BLOCK	32
-#define GPIO_BLOCKS_COUNT	(GPIO_TOTAL_PINS/GPIO_PINS_PER_BLOCK + 1)
-#define GPIO_BLOCK(pin)		(((pin + GPIO_PINS_PER_BLOCK) >> 5) - 1)
-#define GPIO_PIN_WITHIN_BLOCK(pin)	((pin)%(GPIO_PINS_PER_BLOCK))
-
-/* Register in the logic block */
-#define DB8500_GPIO_DAT		0x00
-#define DB8500_GPIO_DATS	0x04
-#define DB8500_GPIO_DATC	0x08
-#define DB8500_GPIO_PDIS	0x0c
-#define DB8500_GPIO_DIR		0x10
-#define DB8500_GPIO_DIRS	0x14
-#define DB8500_GPIO_DIRC	0x18
-#define DB8500_GPIO_SLPC	0x1c
-#define DB8500_GPIO_AFSLA	0x20
-#define DB8500_GPIO_AFSLB	0x24
-
-#define DB8500_GPIO_RIMSC	0x40
-#define DB8500_GPIO_FIMSC	0x44
-#define DB8500_GPIO_IS		0x48
-#define DB8500_GPIO_IC		0x4c
-#define DB8500_GPIO_RWIMSC	0x50
-#define DB8500_GPIO_FWIMSC	0x54
-#define DB8500_GPIO_WKS		0x58
-
-static void __iomem *get_gpio_addr(unsigned gpio)
-{
-	/* Our list of GPIO chips */
-	static void __iomem *gpio_addrs[GPIO_BLOCKS_COUNT] = {
-		IO_ADDR(CFG_GPIO_0_BASE),
-		IO_ADDR(CFG_GPIO_1_BASE),
-		IO_ADDR(CFG_GPIO_2_BASE),
-		IO_ADDR(CFG_GPIO_3_BASE),
-		IO_ADDR(CFG_GPIO_4_BASE),
-		IO_ADDR(CFG_GPIO_5_BASE),
-		IO_ADDR(CFG_GPIO_6_BASE),
-		IO_ADDR(CFG_GPIO_7_BASE),
-		IO_ADDR(CFG_GPIO_8_BASE)
-	};
-
-	return gpio_addrs[GPIO_BLOCK(gpio)];
-}
-
-static unsigned get_gpio_offset(unsigned gpio)
-{
-	return GPIO_PIN_WITHIN_BLOCK(gpio);
-}
-
-/* Can only be called from config_pin. Don't configure alt-mode directly */
-static void gpio_set_mode(unsigned gpio, enum db8500_gpio_alt mode)
-{
-	void __iomem *addr = get_gpio_addr(gpio);
-	unsigned offset = get_gpio_offset(gpio);
-	u32 bit = 1 << offset;
-	u32 afunc, bfunc;
-
-	afunc = readl(addr + DB8500_GPIO_AFSLA) & ~bit;
-	bfunc = readl(addr + DB8500_GPIO_AFSLB) & ~bit;
-	if (mode & DB8500_GPIO_ALT_A)
-		afunc |= bit;
-	if (mode & DB8500_GPIO_ALT_B)
-		bfunc |= bit;
-	writel(afunc, addr + DB8500_GPIO_AFSLA);
-	writel(bfunc, addr + DB8500_GPIO_AFSLB);
-}
-
-/**
- * db8500_gpio_set_pull() - enable/disable pull up/down on a gpio
- * @gpio: pin number
- * @pull: one of DB8500_GPIO_PULL_DOWN, DB8500_GPIO_PULL_UP,
- *  and DB8500_GPIO_PULL_NONE
- *
- * Enables/disables pull up/down on a specified pin.  This only takes effect if
- * the pin is configured as an input (either explicitly or by the alternate
- * function).
- *
- * NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is
- * configured as an input.  Otherwise, due to the way the controller registers
- * work, this function will change the value output on the pin.
- */
-void db8500_gpio_set_pull(unsigned gpio, enum db8500_gpio_pull pull)
-{
-	void __iomem *addr = get_gpio_addr(gpio);
-	unsigned offset = get_gpio_offset(gpio);
-	u32 bit = 1 << offset;
-	u32 pdis;
-
-	pdis = readl(addr + DB8500_GPIO_PDIS);
-	if (pull == DB8500_GPIO_PULL_NONE)
-		pdis |= bit;
-	else
-		pdis &= ~bit;
-	writel(pdis, addr + DB8500_GPIO_PDIS);
-
-	if (pull == DB8500_GPIO_PULL_UP)
-		writel(bit, addr + DB8500_GPIO_DATS);
-	else if (pull == DB8500_GPIO_PULL_DOWN)
-		writel(bit, addr + DB8500_GPIO_DATC);
-}
-
-void db8500_gpio_make_input(unsigned gpio)
-{
-	void __iomem *addr = get_gpio_addr(gpio);
-	unsigned offset = get_gpio_offset(gpio);
-
-	writel(1 << offset, addr + DB8500_GPIO_DIRC);
-}
-
-int db8500_gpio_get_input(unsigned gpio)
-{
-	void __iomem *addr = get_gpio_addr(gpio);
-	unsigned offset = get_gpio_offset(gpio);
-	u32 bit = 1 << offset;
-
-	printf("db8500_gpio_get_input gpio=%u addr=%p offset=%u bit=%#x\n",
-		gpio, addr, offset, bit);
-
-	return (readl(addr + DB8500_GPIO_DAT) & bit) != 0;
-}
-
-void db8500_gpio_make_output(unsigned gpio, int val)
-{
-	void __iomem *addr = get_gpio_addr(gpio);
-	unsigned offset = get_gpio_offset(gpio);
-
-	writel(1 << offset, addr + DB8500_GPIO_DIRS);
-	db8500_gpio_set_output(gpio, val);
-}
-
-void db8500_gpio_set_output(unsigned gpio, int val)
-{
-	void __iomem *addr = get_gpio_addr(gpio);
-	unsigned offset = get_gpio_offset(gpio);
-
-	if (val)
-		writel(1 << offset, addr + DB8500_GPIO_DATS);
-	else
-		writel(1 << offset, addr + DB8500_GPIO_DATC);
-}
-
-/**
- * config_pin - configure a pin's mux attributes
- * @cfg: pin configuration
- *
- * Configures a pin's mode (alternate function or GPIO), its pull up status,
- * and its sleep mode based on the specified configuration.  The @cfg is
- * usually one of the SoC specific macros defined in mach/<soc>-pins.h.  These
- * are constructed using, and can be further enhanced with, the macros in
- * plat/pincfg.h.
- *
- * If a pin's mode is set to GPIO, it is configured as an input to avoid
- * side-effects.  The gpio can be manipulated later using standard GPIO API
- * calls.
- */
-static void config_pin(unsigned long cfg)
-{
-	int pin = PIN_NUM(cfg);
-	int pull = PIN_PULL(cfg);
-	int af = PIN_ALT(cfg);
-	int output = PIN_DIR(cfg);
-	int val = PIN_VAL(cfg);
-
-	if (output)
-		db8500_gpio_make_output(pin, val);
-	else {
-		db8500_gpio_make_input(pin);
-		db8500_gpio_set_pull(pin, pull);
-	}
-
-	gpio_set_mode(pin, af);
-}
-
-/**
- * db8500_config_pins - configure several pins at once
- * @cfgs: array of pin configurations
- * @num: number of elments in the array
- *
- * Configures several pins using config_pin(). Refer to that function for
- * further information.
- */
-void db8500_gpio_config_pins(unsigned long *cfgs, size_t num)
-{
-	size_t i;
-
-	for (i = 0; i < num; i++)
-		config_pin(cfgs[i]);
-}

+ 125 - 0
drivers/gpio/nmk_gpio.c

@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2019 Stephan Gerhold */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+struct nmk_gpio_regs {
+	u32 dat;	/* data */
+	u32 dats;	/* data set */
+	u32 datc;	/* data clear */
+	u32 pdis;	/* pull disable */
+	u32 dir;	/* direction */
+	u32 dirs;	/* direction set */
+	u32 dirc;	/* direction clear */
+	u32 slpm;	/* sleep mode */
+	u32 afsla;	/* alternate function select A */
+	u32 afslb;	/* alternate function select B */
+	u32 lowemi;	/* low EMI mode */
+};
+
+struct nmk_gpio {
+	struct nmk_gpio_regs *regs;
+};
+
+static int nmk_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+	struct nmk_gpio *priv = dev_get_priv(dev);
+
+	return !!(readl(&priv->regs->dat) & BIT(offset));
+}
+
+static int nmk_gpio_set_value(struct udevice *dev, unsigned offset, int value)
+{
+	struct nmk_gpio *priv = dev_get_priv(dev);
+
+	if (value)
+		writel(BIT(offset), &priv->regs->dats);
+	else
+		writel(BIT(offset), &priv->regs->datc);
+
+	return 0;
+}
+
+static int nmk_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+	struct nmk_gpio *priv = dev_get_priv(dev);
+
+	if (readl(&priv->regs->afsla) & BIT(offset) ||
+	    readl(&priv->regs->afslb) & BIT(offset))
+		return GPIOF_FUNC;
+
+	if (readl(&priv->regs->dir) & BIT(offset))
+		return GPIOF_OUTPUT;
+	else
+		return GPIOF_INPUT;
+}
+
+static int nmk_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+	struct nmk_gpio *priv = dev_get_priv(dev);
+
+	writel(BIT(offset), &priv->regs->dirc);
+	return 0;
+}
+
+static int nmk_gpio_direction_output(struct udevice *dev, unsigned offset,
+				     int value)
+{
+	struct nmk_gpio *priv = dev_get_priv(dev);
+
+	writel(BIT(offset), &priv->regs->dirs);
+	return nmk_gpio_set_value(dev, offset, value);
+}
+
+static const struct dm_gpio_ops nmk_gpio_ops = {
+	.get_value		= nmk_gpio_get_value,
+	.set_value		= nmk_gpio_set_value,
+	.get_function		= nmk_gpio_get_function,
+	.direction_input	= nmk_gpio_direction_input,
+	.direction_output	= nmk_gpio_direction_output,
+};
+
+static int nmk_gpio_probe(struct udevice *dev)
+{
+	struct nmk_gpio *priv = dev_get_priv(dev);
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	char buf[20];
+	u32 bank;
+	int ret;
+
+	priv->regs = dev_read_addr_ptr(dev);
+	if (!priv->regs)
+		return -EINVAL;
+
+	ret = dev_read_u32(dev, "gpio-bank", &bank);
+	if (ret < 0) {
+		printf("nmk_gpio(%s): Failed to read gpio-bank\n", dev->name);
+		return ret;
+	}
+
+	sprintf(buf, "nmk%u-gpio", bank);
+	uc_priv->bank_name = strdup(buf);
+	if (!uc_priv->bank_name)
+		return -ENOMEM;
+
+	uc_priv->gpio_count = sizeof(priv->regs->dat) * BITS_PER_BYTE;
+
+	return 0;
+}
+
+static const struct udevice_id nmk_gpio_ids[] = {
+	{ .compatible = "st,nomadik-gpio" },
+	{ }
+};
+
+U_BOOT_DRIVER(gpio_nmk) = {
+	.name		= "nmk_gpio",
+	.id		= UCLASS_GPIO,
+	.of_match	= nmk_gpio_ids,
+	.probe		= nmk_gpio_probe,
+	.ops		= &nmk_gpio_ops,
+	.priv_auto	= sizeof(struct nmk_gpio),
+};

+ 1 - 0
drivers/misc/i2c_eeprom.c

@@ -264,6 +264,7 @@ static const struct i2c_eeprom_drv_data atmel24c512_data = {
 static const struct udevice_id i2c_eeprom_std_ids[] = {
 static const struct udevice_id i2c_eeprom_std_ids[] = {
 	{ .compatible = "i2c-eeprom", (ulong)&eeprom_data },
 	{ .compatible = "i2c-eeprom", (ulong)&eeprom_data },
 	{ .compatible = "microchip,24aa02e48", (ulong)&mc24aa02e48_data },
 	{ .compatible = "microchip,24aa02e48", (ulong)&mc24aa02e48_data },
+	{ .compatible = "atmel,24c01", (ulong)&atmel24c01a_data },
 	{ .compatible = "atmel,24c01a", (ulong)&atmel24c01a_data },
 	{ .compatible = "atmel,24c01a", (ulong)&atmel24c01a_data },
 	{ .compatible = "atmel,24c02", (ulong)&atmel24c02_data },
 	{ .compatible = "atmel,24c02", (ulong)&atmel24c02_data },
 	{ .compatible = "atmel,24c04", (ulong)&atmel24c04_data },
 	{ .compatible = "atmel,24c04", (ulong)&atmel24c04_data },

+ 10 - 0
drivers/pci/Kconfig

@@ -340,4 +340,14 @@ config PCI_BRCMSTB
 	  on Broadcom set-top-box (STB) SoCs.
 	  on Broadcom set-top-box (STB) SoCs.
 	  This driver currently supports only BCM2711 SoC and RC mode
 	  This driver currently supports only BCM2711 SoC and RC mode
 	  of the controller.
 	  of the controller.
+
+config PCIE_UNIPHIER
+	bool "Socionext UniPhier PCIe driver"
+	depends on DM_PCI
+	depends on ARCH_UNIPHIER
+	select PHY_UNIPHIER_PCIE
+	help
+	  Say Y here if you want to enable PCIe controller support on
+	  UniPhier SoCs.
+
 endif
 endif

+ 1 - 0
drivers/pci/Makefile

@@ -56,3 +56,4 @@ obj-$(CONFIG_PCI_BRCMSTB) += pcie_brcmstb.o
 obj-$(CONFIG_PCI_OCTEONTX) += pci_octeontx.o
 obj-$(CONFIG_PCI_OCTEONTX) += pci_octeontx.o
 obj-$(CONFIG_PCIE_OCTEON) += pcie_octeon.o
 obj-$(CONFIG_PCIE_OCTEON) += pcie_octeon.o
 obj-$(CONFIG_PCIE_DW_SIFIVE) += pcie_dw_sifive.o
 obj-$(CONFIG_PCIE_DW_SIFIVE) += pcie_dw_sifive.o
+obj-$(CONFIG_PCIE_UNIPHIER) += pcie_uniphier.o

+ 424 - 0
drivers/pci/pcie_uniphier.c

@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * pcie_uniphier.c - Socionext UniPhier PCIe driver
+ * Copyright 2019-2021 Socionext, Inc.
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <generic-phy.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <pci.h>
+#include <reset.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* DBI registers */
+#define PCIE_LINK_STATUS_REG		0x0080
+#define PCIE_LINK_STATUS_WIDTH_MASK	GENMASK(25, 20)
+#define PCIE_LINK_STATUS_SPEED_MASK	GENMASK(19, 16)
+
+#define PCIE_MISC_CONTROL_1_OFF		0x08BC
+#define PCIE_DBI_RO_WR_EN		BIT(0)
+
+/* DBI iATU registers */
+#define PCIE_ATU_VIEWPORT		0x0900
+#define PCIE_ATU_REGION_INBOUND		BIT(31)
+#define PCIE_ATU_REGION_OUTBOUND	0
+#define PCIE_ATU_REGION_INDEX_MASK	GENMASK(3, 0)
+
+#define PCIE_ATU_CR1			0x0904
+#define PCIE_ATU_TYPE_MEM		0
+#define PCIE_ATU_TYPE_IO		2
+#define PCIE_ATU_TYPE_CFG0		4
+#define PCIE_ATU_TYPE_CFG1		5
+
+#define PCIE_ATU_CR2			0x0908
+#define PCIE_ATU_ENABLE			BIT(31)
+#define PCIE_ATU_MATCH_MODE		BIT(30)
+#define PCIE_ATU_BAR_NUM_MASK		GENMASK(10, 8)
+
+#define PCIE_ATU_LOWER_BASE		0x090C
+#define PCIE_ATU_UPPER_BASE		0x0910
+#define PCIE_ATU_LIMIT			0x0914
+#define PCIE_ATU_LOWER_TARGET		0x0918
+#define PCIE_ATU_BUS(x)			FIELD_PREP(GENMASK(31, 24), x)
+#define PCIE_ATU_DEV(x)			FIELD_PREP(GENMASK(23, 19), x)
+#define PCIE_ATU_FUNC(x)		FIELD_PREP(GENMASK(18, 16), x)
+#define PCIE_ATU_UPPER_TARGET		0x091C
+
+/* Link Glue registers */
+#define PCL_PINCTRL0			0x002c
+#define PCL_PERST_PLDN_REGEN		BIT(12)
+#define PCL_PERST_NOE_REGEN		BIT(11)
+#define PCL_PERST_OUT_REGEN		BIT(8)
+#define PCL_PERST_PLDN_REGVAL		BIT(4)
+#define PCL_PERST_NOE_REGVAL		BIT(3)
+#define PCL_PERST_OUT_REGVAL		BIT(0)
+
+#define PCL_MODE			0x8000
+#define PCL_MODE_REGEN			BIT(8)
+#define PCL_MODE_REGVAL			BIT(0)
+
+#define PCL_APP_READY_CTRL		0x8008
+#define PCL_APP_LTSSM_ENABLE		BIT(0)
+
+#define PCL_APP_PM0			0x8078
+#define PCL_SYS_AUX_PWR_DET		BIT(8)
+
+#define PCL_STATUS_LINK			0x8140
+#define PCL_RDLH_LINK_UP		BIT(1)
+#define PCL_XMLH_LINK_UP		BIT(0)
+
+#define LINK_UP_TIMEOUT_MS		100
+
+struct uniphier_pcie_priv {
+	void *base;
+	void *dbi_base;
+	void *cfg_base;
+	fdt_size_t cfg_size;
+	struct fdt_resource link_res;
+	struct fdt_resource dbi_res;
+	struct fdt_resource cfg_res;
+
+	struct clk clk;
+	struct reset_ctl rst;
+	struct phy phy;
+
+	struct pci_region io;
+	struct pci_region mem;
+};
+
+static int pcie_dw_get_link_speed(struct uniphier_pcie_priv *priv)
+{
+	u32 val = readl(priv->dbi_base + PCIE_LINK_STATUS_REG);
+
+	return FIELD_GET(PCIE_LINK_STATUS_SPEED_MASK, val);
+}
+
+static int pcie_dw_get_link_width(struct uniphier_pcie_priv *priv)
+{
+	u32 val = readl(priv->dbi_base + PCIE_LINK_STATUS_REG);
+
+	return FIELD_GET(PCIE_LINK_STATUS_WIDTH_MASK, val);
+}
+
+static void pcie_dw_prog_outbound_atu(struct uniphier_pcie_priv *priv,
+				      int index, int type, u64 cpu_addr,
+				      u64 pci_addr, u32 size)
+{
+	writel(PCIE_ATU_REGION_OUTBOUND
+	       | FIELD_PREP(PCIE_ATU_REGION_INDEX_MASK, index),
+	       priv->dbi_base + PCIE_ATU_VIEWPORT);
+	writel(lower_32_bits(cpu_addr),
+	       priv->dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(upper_32_bits(cpu_addr),
+	       priv->dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(lower_32_bits(cpu_addr + size - 1),
+	       priv->dbi_base + PCIE_ATU_LIMIT);
+	writel(lower_32_bits(pci_addr),
+	       priv->dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(upper_32_bits(pci_addr),
+	       priv->dbi_base + PCIE_ATU_UPPER_TARGET);
+
+	writel(type, priv->dbi_base + PCIE_ATU_CR1);
+	writel(PCIE_ATU_ENABLE, priv->dbi_base + PCIE_ATU_CR2);
+}
+
+static int uniphier_pcie_addr_valid(pci_dev_t bdf, int first_busno)
+{
+	/* accept only device {0,1} on first bus */
+	if ((PCI_BUS(bdf) != first_busno) || (PCI_DEV(bdf) > 1))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int uniphier_pcie_conf_address(const struct udevice *dev, pci_dev_t bdf,
+				      uint offset, void **paddr)
+{
+	struct uniphier_pcie_priv *priv = dev_get_priv(dev);
+	u32 busdev;
+	int seq = dev_seq(dev);
+	int ret;
+
+	ret = uniphier_pcie_addr_valid(bdf, seq);
+	if (ret)
+		return ret;
+
+	if ((PCI_BUS(bdf) == seq) && !PCI_DEV(bdf)) {
+		*paddr = (void *)(priv->dbi_base + offset);
+		return 0;
+	}
+
+	busdev = PCIE_ATU_BUS(PCI_BUS(bdf) - seq)
+		| PCIE_ATU_DEV(PCI_DEV(bdf))
+		| PCIE_ATU_FUNC(PCI_FUNC(bdf));
+
+	pcie_dw_prog_outbound_atu(priv, 0,
+				  PCIE_ATU_TYPE_CFG0, (u64)priv->cfg_base,
+				  busdev, priv->cfg_size);
+	*paddr = (void *)(priv->cfg_base + offset);
+
+	return 0;
+}
+
+static int uniphier_pcie_read_config(const struct udevice *dev, pci_dev_t bdf,
+				     uint offset, ulong *valp,
+				     enum pci_size_t size)
+{
+	return pci_generic_mmap_read_config(dev, uniphier_pcie_conf_address,
+					    bdf, offset, valp, size);
+}
+
+static int uniphier_pcie_write_config(struct udevice *dev, pci_dev_t bdf,
+				      uint offset, ulong val,
+				      enum pci_size_t size)
+{
+	return pci_generic_mmap_write_config(dev, uniphier_pcie_conf_address,
+					     bdf, offset, val, size);
+}
+
+static void uniphier_pcie_ltssm_enable(struct uniphier_pcie_priv *priv,
+				       bool enable)
+{
+	u32 val;
+
+	val = readl(priv->base + PCL_APP_READY_CTRL);
+	if (enable)
+		val |= PCL_APP_LTSSM_ENABLE;
+	else
+		val &= ~PCL_APP_LTSSM_ENABLE;
+	writel(val, priv->base + PCL_APP_READY_CTRL);
+}
+
+static int uniphier_pcie_link_up(struct uniphier_pcie_priv *priv)
+{
+	u32 val, mask;
+
+	val = readl(priv->base + PCL_STATUS_LINK);
+	mask = PCL_RDLH_LINK_UP | PCL_XMLH_LINK_UP;
+
+	return (val & mask) == mask;
+}
+
+static int uniphier_pcie_wait_link(struct uniphier_pcie_priv *priv)
+{
+	unsigned long timeout;
+
+	timeout = get_timer(0) + LINK_UP_TIMEOUT_MS;
+
+	while (get_timer(0) < timeout) {
+		if (uniphier_pcie_link_up(priv))
+			return 0;
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int uniphier_pcie_establish_link(struct uniphier_pcie_priv *priv)
+{
+	if (uniphier_pcie_link_up(priv))
+		return 0;
+
+	uniphier_pcie_ltssm_enable(priv, true);
+
+	return uniphier_pcie_wait_link(priv);
+}
+
+static void uniphier_pcie_init_rc(struct uniphier_pcie_priv *priv)
+{
+	u32 val;
+
+	/* set RC mode */
+	val = readl(priv->base + PCL_MODE);
+	val |= PCL_MODE_REGEN;
+	val &= ~PCL_MODE_REGVAL;
+	writel(val, priv->base + PCL_MODE);
+
+	/* use auxiliary power detection */
+	val = readl(priv->base + PCL_APP_PM0);
+	val |= PCL_SYS_AUX_PWR_DET;
+	writel(val, priv->base + PCL_APP_PM0);
+
+	/* assert PERST# */
+	val = readl(priv->base + PCL_PINCTRL0);
+	val &= ~(PCL_PERST_NOE_REGVAL | PCL_PERST_OUT_REGVAL
+		 | PCL_PERST_PLDN_REGVAL);
+	val |= PCL_PERST_NOE_REGEN | PCL_PERST_OUT_REGEN
+		| PCL_PERST_PLDN_REGEN;
+	writel(val, priv->base + PCL_PINCTRL0);
+
+	uniphier_pcie_ltssm_enable(priv, false);
+
+	mdelay(100);
+
+	/* deassert PERST# */
+	val = readl(priv->base + PCL_PINCTRL0);
+	val |= PCL_PERST_OUT_REGVAL | PCL_PERST_OUT_REGEN;
+	writel(val, priv->base + PCL_PINCTRL0);
+}
+
+static void uniphier_pcie_setup_rc(struct uniphier_pcie_priv *priv,
+				   struct pci_controller *hose)
+{
+	/* Store the IO and MEM windows settings for future use by the ATU */
+	priv->io.phys_start  = hose->regions[0].phys_start; /* IO base */
+	priv->io.bus_start   = hose->regions[0].bus_start;  /* IO_bus_addr */
+	priv->io.size	     = hose->regions[0].size;	    /* IO size */
+	priv->mem.phys_start = hose->regions[1].phys_start; /* MEM base */
+	priv->mem.bus_start  = hose->regions[1].bus_start;  /* MEM_bus_addr */
+	priv->mem.size	     = hose->regions[1].size;	    /* MEM size */
+
+	/* outbound: IO */
+	pcie_dw_prog_outbound_atu(priv, 0,
+				  PCIE_ATU_TYPE_IO, priv->io.phys_start,
+				  priv->io.bus_start, priv->io.size);
+
+	/* outbound: MEM */
+	pcie_dw_prog_outbound_atu(priv, 1,
+				  PCIE_ATU_TYPE_MEM, priv->mem.phys_start,
+				  priv->mem.bus_start, priv->mem.size);
+}
+
+static int uniphier_pcie_probe(struct udevice *dev)
+{
+	struct uniphier_pcie_priv *priv = dev_get_priv(dev);
+	struct udevice *ctlr = pci_get_controller(dev);
+	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
+	int ret;
+
+	priv->base = map_physmem(priv->link_res.start,
+				 fdt_resource_size(&priv->link_res),
+				 MAP_NOCACHE);
+	priv->dbi_base = map_physmem(priv->dbi_res.start,
+				     fdt_resource_size(&priv->dbi_res),
+				     MAP_NOCACHE);
+	priv->cfg_size = fdt_resource_size(&priv->cfg_res);
+	priv->cfg_base = map_physmem(priv->cfg_res.start,
+				     priv->cfg_size, MAP_NOCACHE);
+
+	ret = clk_enable(&priv->clk);
+	if (ret) {
+		dev_err(dev, "Failed to enable clk: %d\n", ret);
+		return ret;
+	}
+	ret = reset_deassert(&priv->rst);
+	if (ret) {
+		dev_err(dev, "Failed to deassert reset: %d\n", ret);
+		goto out_clk_release;
+	}
+
+	ret = generic_phy_init(&priv->phy);
+	if (ret) {
+		dev_err(dev, "Failed to initialize phy: %d\n", ret);
+		goto out_reset_release;
+	}
+
+	ret = generic_phy_power_on(&priv->phy);
+	if (ret) {
+		dev_err(dev, "Failed to power on phy: %d\n", ret);
+		goto out_phy_exit;
+	}
+
+	uniphier_pcie_init_rc(priv);
+
+	/* set DBI to read only */
+	writel(0, priv->dbi_base + PCIE_MISC_CONTROL_1_OFF);
+
+	uniphier_pcie_setup_rc(priv, hose);
+
+	if (uniphier_pcie_establish_link(priv)) {
+		printf("PCIE-%d: Link down\n", dev_seq(dev));
+	} else {
+		printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n",
+		       dev_seq(dev), pcie_dw_get_link_speed(priv),
+		       pcie_dw_get_link_width(priv), hose->first_busno);
+	}
+
+	return 0;
+
+out_phy_exit:
+	generic_phy_exit(&priv->phy);
+out_reset_release:
+	reset_release_all(&priv->rst, 1);
+out_clk_release:
+	clk_release_all(&priv->clk, 1);
+
+	return ret;
+}
+
+static int uniphier_pcie_of_to_plat(struct udevice *dev)
+{
+	struct uniphier_pcie_priv *priv = dev_get_priv(dev);
+	const void *fdt = gd->fdt_blob;
+	int node = dev_of_offset(dev);
+	int ret;
+
+	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+				     "link", &priv->link_res);
+	if (ret) {
+		dev_err(dev, "Failed to get link regs: %d\n", ret);
+		return ret;
+	}
+
+	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+				     "dbi", &priv->dbi_res);
+	if (ret) {
+		dev_err(dev, "Failed to get dbi regs: %d\n", ret);
+		return ret;
+	}
+
+	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+				     "config", &priv->cfg_res);
+	if (ret) {
+		dev_err(dev, "Failed to get config regs: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_get_by_index(dev, 0, &priv->clk);
+	if (ret) {
+		dev_err(dev, "Failed to get clocks property: %d\n", ret);
+		return ret;
+	}
+
+	ret = reset_get_by_index(dev, 0, &priv->rst);
+	if (ret) {
+		dev_err(dev, "Failed to get resets property: %d\n", ret);
+		return ret;
+	}
+
+	ret = generic_phy_get_by_index(dev, 0, &priv->phy);
+	if (ret) {
+		dev_err(dev, "Failed to get phy property: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct dm_pci_ops uniphier_pcie_ops = {
+	.read_config	= uniphier_pcie_read_config,
+	.write_config	= uniphier_pcie_write_config,
+};
+
+static const struct udevice_id uniphier_pcie_ids[] = {
+	{ .compatible = "socionext,uniphier-pcie", },
+	{ /* Sentinel */ }
+};
+
+U_BOOT_DRIVER(pcie_uniphier) = {
+	.name     = "uniphier-pcie",
+	.id       = UCLASS_PCI,
+	.of_match = uniphier_pcie_ids,
+	.probe    = uniphier_pcie_probe,
+	.ops      = &uniphier_pcie_ops,
+	.of_to_plat = uniphier_pcie_of_to_plat,
+	.priv_auto = sizeof(struct uniphier_pcie_priv),
+};

+ 6 - 0
drivers/phy/Kconfig

@@ -64,6 +64,12 @@ config MIPI_DPHY_HELPERS
 	help
 	help
 	  Provides a number of helpers a core functions for MIPI D-PHY drivers.
 	  Provides a number of helpers a core functions for MIPI D-PHY drivers.
 
 
+config AB8500_USB_PHY
+	bool "AB8500 USB PHY Driver"
+	depends on PHY && PMIC_AB8500
+	help
+	  Support for the USB OTG PHY in ST-Ericsson AB8500.
+
 config BCM6318_USBH_PHY
 config BCM6318_USBH_PHY
 	bool "BCM6318 USBH PHY support"
 	bool "BCM6318 USBH PHY support"
 	depends on PHY && ARCH_BMIPS
 	depends on PHY && ARCH_BMIPS

+ 1 - 0
drivers/phy/Makefile

@@ -6,6 +6,7 @@
 obj-$(CONFIG_$(SPL_)PHY) += phy-uclass.o
 obj-$(CONFIG_$(SPL_)PHY) += phy-uclass.o
 obj-$(CONFIG_$(SPL_)NOP_PHY) += nop-phy.o
 obj-$(CONFIG_$(SPL_)NOP_PHY) += nop-phy.o
 obj-$(CONFIG_MIPI_DPHY_HELPERS) += phy-core-mipi-dphy.o
 obj-$(CONFIG_MIPI_DPHY_HELPERS) += phy-core-mipi-dphy.o
+obj-$(CONFIG_AB8500_USB_PHY) += phy-ab8500-usb.o
 obj-$(CONFIG_BCM6318_USBH_PHY) += bcm6318-usbh-phy.o
 obj-$(CONFIG_BCM6318_USBH_PHY) += bcm6318-usbh-phy.o
 obj-$(CONFIG_BCM6348_USBH_PHY) += bcm6348-usbh-phy.o
 obj-$(CONFIG_BCM6348_USBH_PHY) += bcm6348-usbh-phy.o
 obj-$(CONFIG_BCM6358_USBH_PHY) += bcm6358-usbh-phy.o
 obj-$(CONFIG_BCM6358_USBH_PHY) += bcm6358-usbh-phy.o

+ 52 - 0
drivers/phy/phy-ab8500-usb.c

@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2019 Stephan Gerhold */
+
+#include <common.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <linux/bitops.h>
+#include <power/pmic.h>
+#include <power/ab8500.h>
+
+#define AB8500_USB_PHY_CTRL_REG			AB8500_USB(0x8A)
+#define AB8500_BIT_PHY_CTRL_HOST_EN		BIT(0)
+#define AB8500_BIT_PHY_CTRL_DEVICE_EN		BIT(1)
+#define AB8500_USB_PHY_CTRL_MASK		(AB8500_BIT_PHY_CTRL_HOST_EN |\
+						 AB8500_BIT_PHY_CTRL_DEVICE_EN)
+
+static int ab8500_usb_phy_power_on(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+	uint set = AB8500_BIT_PHY_CTRL_DEVICE_EN;
+
+	if (CONFIG_IS_ENABLED(USB_MUSB_HOST))
+		set = AB8500_BIT_PHY_CTRL_HOST_EN;
+
+	return pmic_clrsetbits(dev->parent, AB8500_USB_PHY_CTRL_REG,
+			       AB8500_USB_PHY_CTRL_MASK, set);
+}
+
+static int ab8500_usb_phy_power_off(struct phy *phy)
+{
+	struct udevice *dev = phy->dev;
+
+	return pmic_clrsetbits(dev->parent, AB8500_USB_PHY_CTRL_REG,
+			       AB8500_USB_PHY_CTRL_MASK, 0);
+}
+
+struct phy_ops ab8500_usb_phy_ops = {
+	.power_on = ab8500_usb_phy_power_on,
+	.power_off = ab8500_usb_phy_power_off,
+};
+
+static const struct udevice_id ab8500_usb_phy_ids[] = {
+	{ .compatible = "stericsson,ab8500-usb" },
+	{ }
+};
+
+U_BOOT_DRIVER(ab8500_usb_phy) = {
+	.name = "ab8500_usb_phy",
+	.id = UCLASS_PHY,
+	.of_match = ab8500_usb_phy_ids,
+	.ops = &ab8500_usb_phy_ops,
+};

+ 12 - 0
drivers/phy/socionext/Kconfig

@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# PHY drivers for Socionext platforms.
+#
+
+config PHY_UNIPHIER_PCIE
+	bool "UniPhier PCIe PHY driver"
+	depends on PHY && ARCH_UNIPHIER
+	imply REGMAP
+	help
+	  Enable this to support PHY implemented in PCIe controller
+	  on UniPhier SoCs.

+ 6 - 0
drivers/phy/socionext/Makefile

@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the phy drivers.
+#
+
+obj-$(CONFIG_PHY_UNIPHIER_PCIE)	+= phy-uniphier-pcie.o

+ 59 - 0
drivers/phy/socionext/phy-uniphier-pcie.c

@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * phy_uniphier_pcie.c - Socionext UniPhier PCIe PHY driver
+ * Copyright 2019-2021 Socionext, Inc.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <regmap.h>
+#include <syscon.h>
+
+/* SG */
+#define SG_USBPCIESEL		0x590
+#define SG_USBPCIESEL_PCIE	BIT(0)
+
+struct uniphier_pciephy_priv {
+	int dummy;
+};
+
+static int uniphier_pciephy_init(struct phy *phy)
+{
+	return 0;
+}
+
+static int uniphier_pciephy_probe(struct udevice *dev)
+{
+	struct regmap *regmap;
+
+	regmap = syscon_regmap_lookup_by_phandle(dev,
+						 "socionext,syscon");
+	if (!IS_ERR(regmap))
+		regmap_update_bits(regmap, SG_USBPCIESEL,
+				   SG_USBPCIESEL_PCIE, SG_USBPCIESEL_PCIE);
+
+	return 0;
+}
+
+static struct phy_ops uniphier_pciephy_ops = {
+	.init = uniphier_pciephy_init,
+};
+
+static const struct udevice_id uniphier_pciephy_ids[] = {
+	{ .compatible = "socionext,uniphier-pro5-pcie-phy" },
+	{ .compatible = "socionext,uniphier-ld20-pcie-phy" },
+	{ .compatible = "socionext,uniphier-pxs3-pcie-phy" },
+	{ }
+};
+
+U_BOOT_DRIVER(uniphier_pcie_phy) = {
+	.name		= "uniphier-pcie-phy",
+	.id		= UCLASS_PHY,
+	.of_match	= uniphier_pciephy_ids,
+	.ops		= &uniphier_pciephy_ops,
+	.probe		= uniphier_pciephy_probe,
+	.priv_auto      = sizeof(struct uniphier_pciephy_priv),
+};

+ 10 - 0
drivers/power/pmic/Kconfig

@@ -31,6 +31,16 @@ config SPL_PMIC_CHILDREN
 	to call your regulator code (e.g. see rk8xx.c for direct functions
 	to call your regulator code (e.g. see rk8xx.c for direct functions
 	for use in SPL).
 	for use in SPL).
 
 
+config PMIC_AB8500
+	bool "Enable driver for ST-Ericsson AB8500 PMIC via PRCMU"
+	depends on DM_PMIC
+	select REGMAP
+	select SYSCON
+	help
+	  Enable support for the ST-Ericsson AB8500 (Analog Baseband) PMIC.
+	  It connects with the ST-Ericsson DB8500 SoC via an I2C bus managed by
+	  the power/reset/clock management unit (PRCMU) firmware.
+
 config PMIC_ACT8846
 config PMIC_ACT8846
 	bool "Enable support for the active-semi 8846 PMIC"
 	bool "Enable support for the active-semi 8846 PMIC"
 	depends on DM_PMIC && DM_I2C
 	depends on DM_PMIC && DM_I2C

+ 1 - 0
drivers/power/pmic/Makefile

@@ -15,6 +15,7 @@ obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
 obj-$(CONFIG_$(SPL_)DM_PMIC_PCA9450) += pca9450.o
 obj-$(CONFIG_$(SPL_)DM_PMIC_PCA9450) += pca9450.o
 obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
 obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
 obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
 obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
+obj-$(CONFIG_PMIC_AB8500) += ab8500.o
 obj-$(CONFIG_PMIC_ACT8846) += act8846.o
 obj-$(CONFIG_PMIC_ACT8846) += act8846.o
 obj-$(CONFIG_PMIC_AS3722) += as3722.o as3722_gpio.o
 obj-$(CONFIG_PMIC_AS3722) += as3722.o as3722_gpio.o
 obj-$(CONFIG_PMIC_MAX8997) += max8997.o
 obj-$(CONFIG_PMIC_MAX8997) += max8997.o

+ 268 - 0
drivers/power/pmic/ab8500.c

@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Stephan Gerhold
+ *
+ * Adapted from old U-Boot and Linux kernel implementation:
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <power/ab8500.h>
+#include <power/pmic.h>
+
+/* CPU mailbox registers */
+#define PRCM_MBOX_CPU_VAL		0x0fc
+#define PRCM_MBOX_CPU_SET		0x100
+#define PRCM_MBOX_CPU_CLR		0x104
+
+#define PRCM_ARM_IT1_CLR		0x48C
+#define PRCM_ARM_IT1_VAL		0x494
+
+#define PRCM_TCDM_RANGE			2
+#define PRCM_REQ_MB5			0xE44
+#define PRCM_ACK_MB5			0xDF4
+#define _PRCM_MBOX_HEADER		0xFE8
+#define PRCM_MBOX_HEADER_REQ_MB5	(_PRCM_MBOX_HEADER + 0x5)
+#define PRCMU_I2C_MBOX_BIT		BIT(5)
+
+/* Mailbox 5 Requests */
+#define PRCM_REQ_MB5_I2C_SLAVE_OP	(PRCM_REQ_MB5 + 0x0)
+#define PRCM_REQ_MB5_I2C_HW_BITS	(PRCM_REQ_MB5 + 0x1)
+#define PRCM_REQ_MB5_I2C_REG		(PRCM_REQ_MB5 + 0x2)
+#define PRCM_REQ_MB5_I2C_VAL		(PRCM_REQ_MB5 + 0x3)
+#define PRCMU_I2C(bank)			(((bank) << 1) | BIT(6))
+#define PRCMU_I2C_WRITE			0
+#define PRCMU_I2C_READ			1
+#define PRCMU_I2C_STOP_EN		BIT(3)
+
+/* Mailbox 5 ACKs */
+#define PRCM_ACK_MB5_I2C_STATUS		(PRCM_ACK_MB5 + 0x1)
+#define PRCM_ACK_MB5_I2C_VAL		(PRCM_ACK_MB5 + 0x3)
+#define PRCMU_I2C_WR_OK			0x1
+#define PRCMU_I2C_RD_OK			0x2
+
+/* AB8500 version registers */
+#define AB8500_MISC_REV_REG		AB8500_MISC(0x80)
+#define AB8500_MISC_IC_NAME_REG		AB8500_MISC(0x82)
+
+struct ab8500_priv {
+	struct ab8500 ab8500;
+	struct regmap *regmap;
+};
+
+static inline int prcmu_tcdm_readb(struct regmap *map, uint offset, u8 *valp)
+{
+	return regmap_raw_read_range(map, PRCM_TCDM_RANGE, offset,
+				     valp, sizeof(*valp));
+}
+
+static inline int prcmu_tcdm_writeb(struct regmap *map, uint offset, u8 val)
+{
+	return regmap_raw_write_range(map, PRCM_TCDM_RANGE, offset,
+				      &val, sizeof(val));
+}
+
+static int prcmu_wait_i2c_mbx_ready(struct ab8500_priv *priv)
+{
+	uint val;
+	int ret;
+
+	ret = regmap_read(priv->regmap, PRCM_ARM_IT1_VAL, &val);
+	if (ret)
+		return ret;
+
+	if (val & PRCMU_I2C_MBOX_BIT) {
+		printf("ab8500: warning: PRCMU i2c mailbox was not acked\n");
+		/* clear mailbox 5 ack irq */
+		ret = regmap_write(priv->regmap, PRCM_ARM_IT1_CLR,
+				   PRCMU_I2C_MBOX_BIT);
+		if (ret)
+			return ret;
+	}
+
+	/* wait for on-going transaction, use 1s timeout */
+	return regmap_read_poll_timeout(priv->regmap, PRCM_MBOX_CPU_VAL, val,
+					!(val & PRCMU_I2C_MBOX_BIT), 0, 1000);
+}
+
+static int prcmu_wait_i2c_mbx_done(struct ab8500_priv *priv)
+{
+	uint val;
+	int ret;
+
+	/* set interrupt to XP70 */
+	ret = regmap_write(priv->regmap, PRCM_MBOX_CPU_SET, PRCMU_I2C_MBOX_BIT);
+	if (ret)
+		return ret;
+
+	/* wait for mailbox 5 (i2c) ack, use 1s timeout */
+	return regmap_read_poll_timeout(priv->regmap, PRCM_ARM_IT1_VAL, val,
+					(val & PRCMU_I2C_MBOX_BIT), 0, 1000);
+}
+
+static int ab8500_transfer(struct udevice *dev, uint bank_reg, u8 *val,
+			   u8 op, u8 expected_status)
+{
+	struct ab8500_priv *priv = dev_get_priv(dev);
+	u8 reg = bank_reg & 0xff;
+	u8 bank = bank_reg >> 8;
+	u8 status;
+	int ret;
+
+	ret = prcmu_wait_i2c_mbx_ready(priv);
+	if (ret)
+		return ret;
+
+	ret = prcmu_tcdm_writeb(priv->regmap, PRCM_MBOX_HEADER_REQ_MB5, 0);
+	if (ret)
+		return ret;
+	ret = prcmu_tcdm_writeb(priv->regmap, PRCM_REQ_MB5_I2C_SLAVE_OP,
+				PRCMU_I2C(bank) | op);
+	if (ret)
+		return ret;
+	ret = prcmu_tcdm_writeb(priv->regmap, PRCM_REQ_MB5_I2C_HW_BITS,
+				PRCMU_I2C_STOP_EN);
+	if (ret)
+		return ret;
+	ret = prcmu_tcdm_writeb(priv->regmap, PRCM_REQ_MB5_I2C_REG, reg);
+	if (ret)
+		return ret;
+	ret = prcmu_tcdm_writeb(priv->regmap, PRCM_REQ_MB5_I2C_VAL, *val);
+	if (ret)
+		return ret;
+
+	ret = prcmu_wait_i2c_mbx_done(priv);
+	if (ret) {
+		printf("%s: mailbox request timed out\n", __func__);
+		return ret;
+	}
+
+	/* read transfer result */
+	ret = prcmu_tcdm_readb(priv->regmap, PRCM_ACK_MB5_I2C_STATUS, &status);
+	if (ret)
+		return ret;
+	ret = prcmu_tcdm_readb(priv->regmap, PRCM_ACK_MB5_I2C_VAL, val);
+	if (ret)
+		return ret;
+
+	/*
+	 * Clear mailbox 5 ack irq. Note that the transfer is already complete
+	 * here so checking for errors does not make sense. Clearing the irq
+	 * will be retried in prcmu_wait_i2c_mbx_ready() on the next transfer.
+	 */
+	regmap_write(priv->regmap, PRCM_ARM_IT1_CLR, PRCMU_I2C_MBOX_BIT);
+
+	if (status != expected_status) {
+		/*
+		 * AB8500 does not have the AB8500_MISC_IC_NAME_REG register,
+		 * but we need to try reading it to detect AB8505.
+		 * In case of an error, assume that we have AB8500.
+		 */
+		if (op == PRCMU_I2C_READ && bank_reg == AB8500_MISC_IC_NAME_REG) {
+			*val = AB8500_VERSION_AB8500;
+			return 0;
+		}
+
+		printf("%s: return status %d\n", __func__, status);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int ab8500_reg_count(struct udevice *dev)
+{
+	return AB8500_NUM_REGISTERS;
+}
+
+static int ab8500_read(struct udevice *dev, uint reg, uint8_t *buf, int len)
+{
+	int ret;
+
+	if (len != 1)
+		return -EINVAL;
+
+	*buf = 0;
+	ret = ab8500_transfer(dev, reg, buf, PRCMU_I2C_READ, PRCMU_I2C_RD_OK);
+	if (ret) {
+		printf("%s failed: %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ab8500_write(struct udevice *dev, uint reg, const uint8_t *buf, int len)
+{
+	int ret;
+	u8 val;
+
+	if (len != 1)
+		return -EINVAL;
+
+	val = *buf;
+	ret = ab8500_transfer(dev, reg, &val, PRCMU_I2C_WRITE, PRCMU_I2C_WR_OK);
+	if (ret) {
+		printf("%s failed: %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct dm_pmic_ops ab8500_ops = {
+	.reg_count = ab8500_reg_count,
+	.read = ab8500_read,
+	.write = ab8500_write,
+};
+
+static int ab8500_probe(struct udevice *dev)
+{
+	struct ab8500_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	/* get regmap from the PRCMU parent device (syscon in U-Boot) */
+	priv->regmap = syscon_get_regmap(dev->parent);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	ret = pmic_reg_read(dev, AB8500_MISC_IC_NAME_REG);
+	if (ret < 0) {
+		printf("ab8500: failed to read chip version: %d\n", ret);
+		return ret;
+	}
+	priv->ab8500.version = ret;
+
+	ret = pmic_reg_read(dev, AB8500_MISC_REV_REG);
+	if (ret < 0) {
+		printf("ab8500: failed to read chip id: %d\n", ret);
+		return ret;
+	}
+	priv->ab8500.chip_id = ret;
+
+	debug("ab8500: version: %#x, chip id: %#x\n",
+	      priv->ab8500.version, priv->ab8500.chip_id);
+
+	return 0;
+}
+
+static const struct udevice_id ab8500_ids[] = {
+	{ .compatible = "stericsson,ab8500" },
+	{ }
+};
+
+U_BOOT_DRIVER(pmic_ab8500) = {
+	.name		= "pmic_ab8500",
+	.id		= UCLASS_PMIC,
+	.of_match	= ab8500_ids,
+	.bind		= dm_scan_fdt_dev,
+	.probe		= ab8500_probe,
+	.ops		= &ab8500_ops,
+	.priv_auto	= sizeof(struct ab8500_priv),
+};

+ 3 - 0
drivers/reset/reset-uniphier.c

@@ -50,6 +50,7 @@ static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
 	UNIPHIER_RESETX(12, 0x2000, 6),		/* GIO */
 	UNIPHIER_RESETX(12, 0x2000, 6),		/* GIO */
 	UNIPHIER_RESETX(14, 0x2000, 17),	/* USB30 */
 	UNIPHIER_RESETX(14, 0x2000, 17),	/* USB30 */
 	UNIPHIER_RESETX(15, 0x2004, 17),	/* USB31 */
 	UNIPHIER_RESETX(15, 0x2004, 17),	/* USB31 */
+	UNIPHIER_RESETX(24, 0x2008, 2),		/* PCIE */
 	UNIPHIER_RESET_END,
 	UNIPHIER_RESET_END,
 };
 };
 
 
@@ -79,6 +80,7 @@ static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
 	UNIPHIER_RESETX(17, 0x200c, 13),	/* USB30-PHY1 */
 	UNIPHIER_RESETX(17, 0x200c, 13),	/* USB30-PHY1 */
 	UNIPHIER_RESETX(18, 0x200c, 14),	/* USB30-PHY2 */
 	UNIPHIER_RESETX(18, 0x200c, 14),	/* USB30-PHY2 */
 	UNIPHIER_RESETX(19, 0x200c, 15),	/* USB30-PHY3 */
 	UNIPHIER_RESETX(19, 0x200c, 15),	/* USB30-PHY3 */
+	UNIPHIER_RESETX(24, 0x200c, 4),		/* PCIE */
 	UNIPHIER_RESET_END,
 	UNIPHIER_RESET_END,
 };
 };
 
 
@@ -95,6 +97,7 @@ static const struct uniphier_reset_data uniphier_pxs3_sys_reset_data[] = {
 	UNIPHIER_RESETX(18, 0x200c, 20),	/* USB30-PHY2 */
 	UNIPHIER_RESETX(18, 0x200c, 20),	/* USB30-PHY2 */
 	UNIPHIER_RESETX(20, 0x200c, 17),	/* USB31-PHY0 */
 	UNIPHIER_RESETX(20, 0x200c, 17),	/* USB31-PHY0 */
 	UNIPHIER_RESETX(21, 0x200c, 19),	/* USB31-PHY1 */
 	UNIPHIER_RESETX(21, 0x200c, 19),	/* USB31-PHY1 */
+	UNIPHIER_RESETX(24, 0x200c, 3),		/* PCIE */
 	UNIPHIER_RESET_END,
 	UNIPHIER_RESET_END,
 };
 };
 
 

+ 2 - 5
drivers/timer/nomadik-mtu-timer.c

@@ -67,14 +67,11 @@ static int nomadik_mtu_probe(struct udevice *dev)
 	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct nomadik_mtu_priv *priv = dev_get_priv(dev);
 	struct nomadik_mtu_priv *priv = dev_get_priv(dev);
 	struct nomadik_mtu_regs *mtu;
 	struct nomadik_mtu_regs *mtu;
-	fdt_addr_t addr;
 	u32 prescale;
 	u32 prescale;
 
 
-	addr = dev_read_addr(dev);
-	if (addr == FDT_ADDR_T_NONE)
+	mtu = dev_read_addr_ptr(dev);
+	if (!mtu)
 		return -EINVAL;
 		return -EINVAL;
-
-	mtu = (struct nomadik_mtu_regs *)addr;
 	priv->timer = mtu->timers; /* Use first timer */
 	priv->timer = mtu->timers; /* Use first timer */
 
 
 	if (!uc_priv->clock_rate)
 	if (!uc_priv->clock_rate)

+ 10 - 1
drivers/usb/musb-new/Kconfig

@@ -72,6 +72,15 @@ config USB_MUSB_SUNXI
 	Say y here to enable support for the sunxi OTG / DRC USB controller
 	Say y here to enable support for the sunxi OTG / DRC USB controller
 	used on almost all sunxi boards.
 	used on almost all sunxi boards.
 
 
+config USB_MUSB_UX500
+	bool "Enable ST-Ericsson Ux500 USB controller"
+	depends on DM_USB && DM_USB_GADGET && ARCH_U8500
+	default y
+	help
+	  Say y to enable support for the MUSB OTG USB controller used in
+	  ST-Ericsson Ux500. The driver supports either gadget or host mode
+	  based on the selection of CONFIG_USB_MUSB_HOST.
+
 config USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
 config USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
 	bool "Disable MUSB bulk split/combine"
 	bool "Disable MUSB bulk split/combine"
 	default y
 	default y
@@ -85,7 +94,7 @@ endif
 
 
 config USB_MUSB_PIO_ONLY
 config USB_MUSB_PIO_ONLY
 	bool "Disable DMA (always use PIO)"
 	bool "Disable DMA (always use PIO)"
-	default y if USB_MUSB_AM35X || USB_MUSB_PIC32 || USB_MUSB_OMAP2PLUS || USB_MUSB_DSPS || USB_MUSB_SUNXI || USB_MUSB_MT85XX
+	default y if USB_MUSB_AM35X || USB_MUSB_PIC32 || USB_MUSB_OMAP2PLUS || USB_MUSB_DSPS || USB_MUSB_SUNXI || USB_MUSB_MT85XX || USB_MUSB_UX500
 	help
 	help
 	  All data is copied between memory and FIFO by the CPU.
 	  All data is copied between memory and FIFO by the CPU.
 	  DMA controllers are ignored.
 	  DMA controllers are ignored.

+ 1 - 0
drivers/usb/musb-new/Makefile

@@ -13,6 +13,7 @@ obj-$(CONFIG_USB_MUSB_OMAP2PLUS) += omap2430.o
 obj-$(CONFIG_USB_MUSB_PIC32) += pic32.o
 obj-$(CONFIG_USB_MUSB_PIC32) += pic32.o
 obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o
 obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o
 obj-$(CONFIG_USB_MUSB_TI) += ti-musb.o
 obj-$(CONFIG_USB_MUSB_TI) += ti-musb.o
+obj-$(CONFIG_USB_MUSB_UX500) += ux500.o
 
 
 ccflags-y := $(call cc-option,-Wno-unused-variable) \
 ccflags-y := $(call cc-option,-Wno-unused-variable) \
 		$(call cc-option,-Wno-unused-but-set-variable) \
 		$(call cc-option,-Wno-unused-but-set-variable) \

+ 1 - 1
drivers/usb/musb-new/musb_core.c

@@ -1526,7 +1526,7 @@ static int __devinit musb_core_init(u16 musb_type, struct musb *musb)
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
 #if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
 #if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
-	defined(CONFIG_ARCH_OMAP4)
+	defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)
 
 
 static irqreturn_t generic_interrupt(int irq, void *__hci)
 static irqreturn_t generic_interrupt(int irq, void *__hci)
 {
 {

+ 179 - 0
drivers/usb/musb-new/ux500.c

@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2019 Stephan Gerhold */
+
+#include <common.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <dm/device_compat.h>
+#include "musb_uboot.h"
+
+static struct musb_hdrc_config ux500_musb_hdrc_config = {
+	.multipoint	= true,
+	.dyn_fifo	= true,
+	.num_eps	= 16,
+	.ram_bits	= 16,
+};
+
+struct ux500_glue {
+	struct musb_host_data mdata;
+	struct device dev;
+	struct phy phy;
+	bool enabled;
+};
+#define to_ux500_glue(d)	container_of(d, struct ux500_glue, dev)
+
+static int ux500_musb_enable(struct musb *musb)
+{
+	struct ux500_glue *glue = to_ux500_glue(musb->controller);
+	int ret;
+
+	if (glue->enabled)
+		return 0;
+
+	ret = generic_phy_power_on(&glue->phy);
+	if (ret) {
+		printf("%s: failed to power on USB PHY\n", __func__);
+		return ret;
+	}
+
+	glue->enabled = true;
+	return 0;
+}
+
+static void ux500_musb_disable(struct musb *musb)
+{
+	struct ux500_glue *glue = to_ux500_glue(musb->controller);
+	int ret;
+
+	if (!glue->enabled)
+		return;
+
+	ret = generic_phy_power_off(&glue->phy);
+	if (ret) {
+		printf("%s: failed to power off USB PHY\n", __func__);
+		return;
+	}
+
+	glue->enabled = false;
+}
+
+static int ux500_musb_init(struct musb *musb)
+{
+	struct ux500_glue *glue = to_ux500_glue(musb->controller);
+	int ret;
+
+	ret = generic_phy_init(&glue->phy);
+	if (ret) {
+		printf("%s: failed to init USB PHY\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ux500_musb_exit(struct musb *musb)
+{
+	struct ux500_glue *glue = to_ux500_glue(musb->controller);
+	int ret;
+
+	ret = generic_phy_exit(&glue->phy);
+	if (ret) {
+		printf("%s: failed to exit USB PHY\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct musb_platform_ops ux500_musb_ops = {
+	.init		= ux500_musb_init,
+	.exit		= ux500_musb_exit,
+	.enable		= ux500_musb_enable,
+	.disable	= ux500_musb_disable,
+};
+
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
+{
+	struct ux500_glue *glue = dev_get_priv(dev);
+
+	glue->mdata.host->isr(0, glue->mdata.host);
+	return 0;
+}
+
+static int ux500_musb_probe(struct udevice *dev)
+{
+#ifdef CONFIG_USB_MUSB_HOST
+	struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
+#endif
+	struct ux500_glue *glue = dev_get_priv(dev);
+	struct musb_host_data *host = &glue->mdata;
+	struct musb_hdrc_platform_data pdata;
+	void *base = dev_read_addr_ptr(dev);
+	int ret;
+
+	if (!base)
+		return -EINVAL;
+
+	ret = generic_phy_get_by_name(dev, "usb", &glue->phy);
+	if (ret) {
+		dev_err(dev, "failed to get USB PHY: %d\n", ret);
+		return ret;
+	}
+
+	memset(&pdata, 0, sizeof(pdata));
+	pdata.platform_ops = &ux500_musb_ops;
+	pdata.config = &ux500_musb_hdrc_config;
+
+#ifdef CONFIG_USB_MUSB_HOST
+	priv->desc_before_addr = true;
+	pdata.mode = MUSB_HOST;
+
+	host->host = musb_init_controller(&pdata, &glue->dev, base);
+	if (!host->host)
+		return -EIO;
+
+	return musb_lowlevel_init(host);
+#else
+	pdata.mode = MUSB_PERIPHERAL;
+	host->host = musb_init_controller(&pdata, &glue->dev, base);
+	if (!host->host)
+		return -EIO;
+
+	return usb_add_gadget_udc(&glue->dev, &host->host->g);
+#endif
+}
+
+static int ux500_musb_remove(struct udevice *dev)
+{
+	struct ux500_glue *glue = dev_get_priv(dev);
+	struct musb_host_data *host = &glue->mdata;
+
+	usb_del_gadget_udc(&host->host->g);
+	musb_stop(host->host);
+	free(host->host);
+	host->host = NULL;
+
+	return 0;
+}
+
+static const struct udevice_id ux500_musb_ids[] = {
+	{ .compatible = "stericsson,db8500-musb" },
+	{ }
+};
+
+U_BOOT_DRIVER(ux500_musb) = {
+	.name		= "ux500-musb",
+#ifdef CONFIG_USB_MUSB_HOST
+	.id		= UCLASS_USB,
+#else
+	.id		= UCLASS_USB_GADGET_GENERIC,
+#endif
+	.of_match	= ux500_musb_ids,
+	.probe		= ux500_musb_probe,
+	.remove		= ux500_musb_remove,
+#ifdef CONFIG_USB_MUSB_HOST
+	.ops		= &musb_usb_ops,
+#endif
+	.plat_auto	= sizeof(struct usb_plat),
+	.priv_auto	= sizeof(struct ux500_glue),
+};

+ 12 - 12
include/configs/stemmy.h

@@ -7,23 +7,23 @@
 
 
 #include <linux/sizes.h>
 #include <linux/sizes.h>
 
 
-#define CONFIG_SKIP_LOWLEVEL_INIT	/* Loaded by another bootloader */
-#define CONFIG_SYS_MALLOC_LEN		SZ_2M
+/*
+ * The "stemmy" U-Boot port is designed to be chainloaded by the Samsung
+ * bootloader on devices based on ST-Ericsson Ux500. Therefore, we skip most
+ * low-level initialization and rely on configuration provided by the Samsung
+ * bootloader. New images are loaded at the same address for compatibility.
+ */
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_SYS_INIT_SP_ADDR		CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_SYS_TEXT_BASE
 
 
-/* Physical Memory Map */
-#define PHYS_SDRAM_1			0x00000000	/* DDR-SDRAM Bank #1 */
-#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
-#define CONFIG_SYS_SDRAM_SIZE		SZ_1G
-#define CONFIG_SYS_INIT_RAM_SIZE	0x00100000
-#define CONFIG_SYS_GBL_DATA_OFFSET	(CONFIG_SYS_SDRAM_BASE + \
-					 CONFIG_SYS_INIT_RAM_SIZE - \
-					 GENERATED_GBL_DATA_SIZE)
-#define CONFIG_SYS_INIT_SP_ADDR		CONFIG_SYS_GBL_DATA_OFFSET
+#define CONFIG_SYS_MALLOC_LEN		SZ_2M
 
 
 /* FIXME: This should be loaded from device tree... */
 /* FIXME: This should be loaded from device tree... */
 #define CONFIG_SYS_L2_PL310
 #define CONFIG_SYS_L2_PL310
 #define CONFIG_SYS_PL310_BASE		0xa0412000
 #define CONFIG_SYS_PL310_BASE		0xa0412000
 
 
-#define CONFIG_SYS_LOAD_ADDR		0x00100000
+/* Generate initrd atag for downstream kernel (others are copied in stemmy.c) */
+#define CONFIG_INITRD_TAG
 
 
 #endif
 #endif

+ 2 - 0
include/configs/uniphier.h

@@ -210,4 +210,6 @@
 
 
 #define CONFIG_SPL_PAD_TO			0x20000
 #define CONFIG_SPL_PAD_TO			0x20000
 
 
+#define CONFIG_SYS_PCI_64BIT
+
 #endif /* __CONFIG_UNIPHIER_H__ */
 #endif /* __CONFIG_UNIPHIER_H__ */

+ 125 - 0
include/power/ab8500.h

@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Based on include/linux/mfd/abx500/ab8500.h from Linux
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
+ */
+
+#ifndef _PMIC_AB8500_H_
+#define _PMIC_AB8500_H_
+
+/*
+ * AB IC versions
+ *
+ * AB8500_VERSION_AB8500 should be 0xFF but will never be read as need a
+ * non-supported multi-byte I2C access via PRCMU. Set to 0x00 to ease the
+ * print of version string.
+ */
+enum ab8500_version {
+	AB8500_VERSION_AB8500 = 0x0,
+	AB8500_VERSION_AB8505 = 0x1,
+	AB8500_VERSION_AB9540 = 0x2,
+	AB8500_VERSION_AB8540 = 0x4,
+	AB8500_VERSION_UNDEFINED,
+};
+
+/* AB8500 CIDs*/
+#define AB8500_CUTEARLY	0x00
+#define AB8500_CUT1P0	0x10
+#define AB8500_CUT1P1	0x11
+#define AB8500_CUT1P2	0x12 /* Only valid for AB8540 */
+#define AB8500_CUT2P0	0x20
+#define AB8500_CUT3P0	0x30
+#define AB8500_CUT3P3	0x33
+
+/*
+ * AB8500 bank addresses
+ */
+#define AB8500_BANK(bank, reg)		(((bank) << 8) | (reg))
+#define AB8500_M_FSM_RANK(reg)		AB8500_BANK(0x0, reg)
+#define AB8500_SYS_CTRL1_BLOCK(reg)	AB8500_BANK(0x1, reg)
+#define AB8500_SYS_CTRL2_BLOCK(reg)	AB8500_BANK(0x2, reg)
+#define AB8500_REGU_CTRL1(reg)		AB8500_BANK(0x3, reg)
+#define AB8500_REGU_CTRL2(reg)		AB8500_BANK(0x4, reg)
+#define AB8500_USB(reg)			AB8500_BANK(0x5, reg)
+#define AB8500_TVOUT(reg)		AB8500_BANK(0x6, reg)
+#define AB8500_DBI(reg)			AB8500_BANK(0x7, reg)
+#define AB8500_ECI_AV_ACC(reg)		AB8500_BANK(0x8, reg)
+#define AB8500_RESERVED(reg)		AB8500_BANK(0x9, reg)
+#define AB8500_GPADC(reg)		AB8500_BANK(0xA, reg)
+#define AB8500_CHARGER(reg)		AB8500_BANK(0xB, reg)
+#define AB8500_GAS_GAUGE(reg)		AB8500_BANK(0xC, reg)
+#define AB8500_AUDIO(reg)		AB8500_BANK(0xD, reg)
+#define AB8500_INTERRUPT(reg)		AB8500_BANK(0xE, reg)
+#define AB8500_RTC(reg)			AB8500_BANK(0xF, reg)
+#define AB8500_GPIO(reg)		AB8500_BANK(0x10, reg)
+#define AB8500_MISC(reg)		AB8500_BANK(0x10, reg)
+#define AB8500_DEVELOPMENT(reg)		AB8500_BANK(0x11, reg)
+#define AB8500_DEBUG(reg)		AB8500_BANK(0x12, reg)
+#define AB8500_PROD_TEST(reg)		AB8500_BANK(0x13, reg)
+#define AB8500_STE_TEST(reg)		AB8500_BANK(0x14, reg)
+#define AB8500_OTP_EMUL(reg)		AB8500_BANK(0x15, reg)
+
+#define AB8500_NUM_BANKS		0x16
+#define AB8500_NUM_REGISTERS		AB8500_BANK(AB8500_NUM_BANKS, 0)
+
+struct ab8500 {
+	enum ab8500_version version;
+	u8 chip_id;
+};
+
+static inline int is_ab8500(struct ab8500 *ab)
+{
+	return ab->version == AB8500_VERSION_AB8500;
+}
+
+static inline int is_ab8505(struct ab8500 *ab)
+{
+	return ab->version == AB8500_VERSION_AB8505;
+}
+
+/* exclude also ab8505, ab9540... */
+static inline int is_ab8500_1p0_or_earlier(struct ab8500 *ab)
+{
+	return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT1P0));
+}
+
+/* exclude also ab8505, ab9540... */
+static inline int is_ab8500_1p1_or_earlier(struct ab8500 *ab)
+{
+	return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT1P1));
+}
+
+/* exclude also ab8505, ab9540... */
+static inline int is_ab8500_2p0_or_earlier(struct ab8500 *ab)
+{
+	return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT2P0));
+}
+
+static inline int is_ab8500_3p3_or_earlier(struct ab8500 *ab)
+{
+	return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT3P3));
+}
+
+/* exclude also ab8505, ab9540... */
+static inline int is_ab8500_2p0(struct ab8500 *ab)
+{
+	return (is_ab8500(ab) && (ab->chip_id == AB8500_CUT2P0));
+}
+
+static inline int is_ab8505_1p0_or_earlier(struct ab8500 *ab)
+{
+	return (is_ab8505(ab) && (ab->chip_id <= AB8500_CUT1P0));
+}
+
+static inline int is_ab8505_2p0(struct ab8500 *ab)
+{
+	return (is_ab8505(ab) && (ab->chip_id == AB8500_CUT2P0));
+}
+
+static inline int is_ab8505_2p0_earlier(struct ab8500 *ab)
+{
+	return (is_ab8505(ab) && (ab->chip_id < AB8500_CUT2P0));
+}
+
+#endif