summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2016-09-27 11:40:56 -0400
committerTom Rini <trini@konsulko.com>2016-09-27 11:40:56 -0400
commit6d5565608f385b89f528ecf5680410cdc6cf63e9 (patch)
tree9403a25d40b8546e1e8a77fbe70da67c5ed4ade0
parente120c848bac77cfcc88183541c2e966e625a7840 (diff)
parentb28d29f784f5cc33c92e291d35eda603ea4e58e3 (diff)
downloadu-boot-6d5565608f385b89f528ecf5680410cdc6cf63e9.tar.gz
Merge git://www.denx.de/git/u-boot-marvell
-rw-r--r--arch/arm/Kconfig8
-rw-r--r--arch/arm/dts/Makefile2
-rw-r--r--arch/arm/dts/armada-371x.dtsi53
-rw-r--r--arch/arm/dts/armada-3720-db.dts123
-rw-r--r--arch/arm/dts/armada-372x.dtsi62
-rw-r--r--arch/arm/dts/armada-37xx.dtsi189
-rw-r--r--arch/arm/dts/armada-7040-db.dts193
-rw-r--r--arch/arm/dts/armada-7040.dtsi55
-rw-r--r--arch/arm/dts/armada-ap806-quad.dtsi82
-rw-r--r--arch/arm/dts/armada-ap806.dtsi230
-rw-r--r--arch/arm/dts/armada-cp110-master.dtsi256
-rw-r--r--arch/arm/mach-mvebu/Kconfig44
-rw-r--r--arch/arm/mach-mvebu/Makefile18
-rw-r--r--arch/arm/mach-mvebu/arm64-common.c124
-rw-r--r--arch/arm/mach-mvebu/armada3700/Makefile7
-rw-r--r--arch/arm/mach-mvebu/armada3700/cpu.c81
-rw-r--r--arch/arm/mach-mvebu/armada8k/Makefile7
-rw-r--r--arch/arm/mach-mvebu/armada8k/cpu.c64
-rw-r--r--arch/arm/mach-mvebu/include/mach/cpu.h7
-rw-r--r--arch/arm/mach-mvebu/include/mach/soc.h4
-rw-r--r--arch/arm/mach-mvebu/sata.c54
-rw-r--r--board/Marvell/mvebu_db-88f3720/MAINTAINERS6
-rw-r--r--board/Marvell/mvebu_db-88f3720/Makefile7
-rw-r--r--board/Marvell/mvebu_db-88f3720/board.c134
-rw-r--r--board/Marvell/mvebu_db-88f7040/MAINTAINERS6
-rw-r--r--board/Marvell/mvebu_db-88f7040/Makefile7
-rw-r--r--board/Marvell/mvebu_db-88f7040/board.c152
-rw-r--r--configs/mvebu_db-88f3720_defconfig49
-rw-r--r--configs/mvebu_db-88f7040_defconfig47
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/block/ahci.c2
-rw-r--r--drivers/net/mvneta.c51
-rw-r--r--drivers/phy/marvell/Kconfig9
-rw-r--r--drivers/phy/marvell/Makefile8
-rw-r--r--drivers/phy/marvell/comphy.h153
-rw-r--r--drivers/phy/marvell/comphy_a3700.c962
-rw-r--r--drivers/phy/marvell/comphy_a3700.h275
-rw-r--r--drivers/phy/marvell/comphy_core.c200
-rw-r--r--drivers/phy/marvell/comphy_cp110.c1726
-rw-r--r--drivers/phy/marvell/comphy_hpipe.h420
-rw-r--r--drivers/phy/marvell/comphy_mux.c118
-rw-r--r--drivers/phy/marvell/sata.h30
-rw-r--r--drivers/phy/marvell/utmi_phy.h90
-rw-r--r--drivers/serial/Kconfig15
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/serial_mvebu_a3700.c175
-rw-r--r--drivers/spi/Kconfig7
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/mvebu_a3700_spi.c295
-rw-r--r--drivers/usb/host/Kconfig9
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/ehci-marvell.c59
-rw-r--r--drivers/usb/host/xhci-mvebu.c97
-rw-r--r--include/configs/mvebu_db-88f3720.h144
-rw-r--r--include/configs/mvebu_db-88f7040.h133
-rw-r--r--include/dt-bindings/comphy/comphy_data.h61
57 files changed, 7087 insertions, 29 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 38ad59058f..1e4830a30e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -164,9 +164,7 @@ config KIRKWOOD
select CPU_ARM926EJS
config ARCH_MVEBU
- bool "Marvell MVEBU family (Armada XP/375/38x)"
- select CPU_V7
- select SUPPORT_SPL
+ bool "Marvell MVEBU family (Armada XP/375/38x/3700/7K/8K)"
select OF_CONTROL
select OF_SEPARATE
select DM
@@ -174,10 +172,6 @@ config ARCH_MVEBU
select DM_SERIAL
select DM_SPI
select DM_SPI_FLASH
- select SPL_DM
- select SPL_DM_SEQ_ALIAS
- select SPL_OF_CONTROL
- select SPL_SIMPLE_BUS
config TARGET_DEVKIT3250
bool "Support devkit3250"
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index e89b6e8074..032c5aebc1 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -67,10 +67,12 @@ dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
tegra210-p2571.dtb
dtb-$(CONFIG_ARCH_MVEBU) += \
+ armada-3720-db.dtb \
armada-375-db.dtb \
armada-388-clearfog.dtb \
armada-388-gp.dtb \
armada-385-amc.dtb \
+ armada-7040-db.dtb \
armada-xp-gp.dtb \
armada-xp-maxbcm.dtb \
armada-xp-synology-ds414.dtb \
diff --git a/arch/arm/dts/armada-371x.dtsi b/arch/arm/dts/armada-371x.dtsi
new file mode 100644
index 0000000000..c9e5325b8a
--- /dev/null
+++ b/arch/arm/dts/armada-371x.dtsi
@@ -0,0 +1,53 @@
+/*
+ * Device Tree Include file for Marvell Armada 371x family of SoCs
+ * (also named 88F3710)
+ *
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "armada-37xx.dtsi"
+
+/ {
+ model = "Marvell Armada 3710 SoC";
+ compatible = "marvell,armada3710", "marvell,armada3700";
+};
diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts
new file mode 100644
index 0000000000..83967eeac4
--- /dev/null
+++ b/arch/arm/dts/armada-3720-db.dts
@@ -0,0 +1,123 @@
+/*
+ * Device Tree file for Marvell Armada 3720 development board
+ * (DB-88F3720-DDR3)
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "armada-372x.dtsi"
+
+/ {
+ model = "Marvell Armada 3720 Development Board DB-88F3720-DDR3";
+ compatible = "marvell,armada-3720-db", "marvell,armada3720", "marvell,armada3710";
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ aliases {
+ ethernet0 = &eth0;
+ i2c0 = &i2c0;
+ spi0 = &spi0;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+ };
+};
+
+&comphy {
+ phy0 {
+ phy-type = <PHY_TYPE_PEX0>;
+ phy-speed = <PHY_SPEED_2_5G>;
+ };
+
+ phy1 {
+ phy-type = <PHY_TYPE_USB3_HOST0>;
+ phy-speed = <PHY_SPEED_5G>;
+ };
+};
+
+&eth0 {
+ status = "okay";
+ phy-mode = "rgmii";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+/* CON3 */
+&sata {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+
+ spi-flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,m25p128", "spi-flash";
+ reg = <0>; /* Chip select 0 */
+ spi-max-frequency = <50000000>;
+ m25p,fast-read;
+ };
+};
+
+/* Exported on the micro USB connector CON32 through an FTDI */
+&uart0 {
+ status = "okay";
+};
+
+/* CON29 */
+&usb2 {
+ status = "okay";
+};
+
+/* CON31 */
+&usb3 {
+ status = "okay";
+};
diff --git a/arch/arm/dts/armada-372x.dtsi b/arch/arm/dts/armada-372x.dtsi
new file mode 100644
index 0000000000..5120296596
--- /dev/null
+++ b/arch/arm/dts/armada-372x.dtsi
@@ -0,0 +1,62 @@
+/*
+ * Device Tree Include file for Marvell Armada 372x family of SoCs
+ * (also named 88F3720)
+ *
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "armada-37xx.dtsi"
+
+/ {
+ model = "Marvell Armada 3720 SoC";
+ compatible = "marvell,armada3720", "marvell,armada3710";
+
+ cpus {
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53","arm,armv8";
+ reg = <0x1>;
+ enable-method = "psci";
+ };
+ };
+};
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi
new file mode 100644
index 0000000000..e27eae0362
--- /dev/null
+++ b/arch/arm/dts/armada-37xx.dtsi
@@ -0,0 +1,189 @@
+/*
+ * Device Tree Include file for Marvell Armada 37xx family of SoCs.
+ *
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/comphy/comphy_data.h>
+
+/ {
+ model = "Marvell Armada 37xx SoC";
+ compatible = "marvell,armada3700";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53", "arm,armv8";
+ reg = <0>;
+ enable-method = "psci";
+ };
+ };
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13
+ (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 14
+ (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 11
+ (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 10
+ (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ internal-regs {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ /* 32M internal register @ 0xd000_0000 */
+ ranges = <0x0 0x0 0xd0000000 0x2000000>;
+
+ uart0: serial@12000 {
+ compatible = "marvell,armada-3700-uart";
+ reg = <0x12000 0x400>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ usb3: usb@58000 {
+ compatible = "marvell,armada3700-xhci",
+ "generic-xhci";
+ reg = <0x58000 0x4000>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ usb2: usb@5e000 {
+ compatible = "marvell,armada3700-ehci";
+ reg = <0x5e000 0x450>;
+ status = "disabled";
+ };
+
+ xor@60900 {
+ compatible = "marvell,armada-3700-xor";
+ reg = <0x60900 0x100
+ 0x60b00 0x100>;
+
+ xor10 {
+ interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ xor11 {
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ sata: sata@e0000 {
+ compatible = "marvell,armada-3700-ahci";
+ reg = <0xe0000 0x2000>;
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@1d00000 {
+ compatible = "arm,gic-v3";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x1d00000 0x10000>, /* GICD */
+ <0x1d40000 0x40000>; /* GICR */
+ };
+
+ eth0: neta@30000 {
+ compatible = "marvell,armada-3700-neta";
+ reg = <0x30000 0x20>;
+ status = "disabled";
+ };
+
+ eth1: neta@40000 {
+ compatible = "marvell,armada-3700-neta";
+ reg = <0x40000 0x20>;
+ status = "disabled";
+ };
+
+ i2c0: i2c@11000 {
+ compatible = "marvell,armada-3700-i2c";
+ reg = <0x11000 0x100>;
+ status = "disabled";
+ };
+
+ spi0: spi@10600 {
+ compatible = "marvell,armada-3700-spi";
+ reg = <0x10600 0x50>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <0>;
+ clock-frequency = <160000>;
+ spi-max-frequency = <40000>;
+ status = "disabled";
+ };
+
+ comphy: comphy@18300 {
+ compatible = "marvell,mvebu-comphy", "marvell,comphy-armada-3700";
+ reg = <0x18300 0x28>,
+ <0x1f300 0x3d000>;
+ mux-bitcount = <1>;
+ max-lanes = <2>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts
new file mode 100644
index 0000000000..7d0059afe5
--- /dev/null
+++ b/arch/arm/dts/armada-7040-db.dts
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2016 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Device Tree file for Marvell Armada 7040 Development board platform
+ */
+
+#include "armada-7040.dtsi"
+
+/ {
+ model = "Marvell Armada 7040 DB board";
+ compatible = "marvell,armada7040-db", "marvell,armada7040",
+ "marvell,armada-ap806-quad", "marvell,armada-ap806";
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ aliases {
+ i2c0 = &cpm_i2c0;
+ spi0 = &cpm_spi1;
+ };
+
+ memory@00000000 {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x80000000>;
+ };
+};
+
+&i2c0 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&spi0 {
+ status = "okay";
+
+ spi-flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0 0x200000>;
+ };
+ partition@400000 {
+ label = "Filesystem";
+ reg = <0x200000 0xce0000>;
+ };
+ };
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+
+&cpm_pcie2 {
+ status = "okay";
+};
+
+&cpm_i2c0 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&cpm_spi1 {
+ status = "okay";
+
+ spi-flash@0 {
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-max-frequency = <20000000>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0x0 0x200000>;
+ };
+
+ partition@400000 {
+ label = "Filesystem";
+ reg = <0x200000 0xe00000>;
+ };
+ };
+ };
+};
+
+&cpm_sata0 {
+ status = "okay";
+};
+
+&cpm_usb3_0 {
+ status = "okay";
+};
+
+&cpm_usb3_1 {
+ status = "okay";
+};
+
+&comphy_cp110 {
+ phy0 {
+ phy-type = <PHY_TYPE_SGMII2>;
+ phy-speed = <PHY_SPEED_3_125G>;
+ };
+
+ phy1 {
+ phy-type = <PHY_TYPE_USB3_HOST0>;
+ phy-speed = <PHY_SPEED_5G>;
+ };
+
+ phy2 {
+ phy-type = <PHY_TYPE_SGMII0>;
+ phy-speed = <PHY_SPEED_1_25G>;
+ };
+
+ phy3 {
+ phy-type = <PHY_TYPE_SATA1>;
+ phy-speed = <PHY_SPEED_5G>;
+ };
+
+ phy4 {
+ phy-type = <PHY_TYPE_USB3_HOST1>;
+ phy-speed = <PHY_SPEED_5G>;
+ };
+
+ phy5 {
+ phy-type = <PHY_TYPE_PEX2>;
+ phy-speed = <PHY_SPEED_5G>;
+ };
+};
+
+&utmi0 {
+ status = "okay";
+};
+
+&utmi1 {
+ status = "okay";
+};
diff --git a/arch/arm/dts/armada-7040.dtsi b/arch/arm/dts/armada-7040.dtsi
new file mode 100644
index 0000000000..78d995d627
--- /dev/null
+++ b/arch/arm/dts/armada-7040.dtsi
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Device Tree file for the Armada 7040 SoC, made of an AP806 Quad and
+ * one CP110.
+ */
+
+#include "armada-ap806-quad.dtsi"
+#include "armada-cp110-master.dtsi"
+
+/ {
+ model = "Marvell Armada 7040";
+ compatible = "marvell,armada7040", "marvell,armada-ap806-quad",
+ "marvell,armada-ap806";
+};
diff --git a/arch/arm/dts/armada-ap806-quad.dtsi b/arch/arm/dts/armada-ap806-quad.dtsi
new file mode 100644
index 0000000000..ba43a4357b
--- /dev/null
+++ b/arch/arm/dts/armada-ap806-quad.dtsi
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Device Tree file for Marvell Armada AP806.
+ */
+
+#include "armada-ap806.dtsi"
+
+/ {
+ model = "Marvell Armada AP806 Quad";
+ compatible = "marvell,armada-ap806-quad", "marvell,armada-ap806";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@000 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72", "arm,armv8";
+ reg = <0x000>;
+ enable-method = "psci";
+ };
+ cpu@001 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72", "arm,armv8";
+ reg = <0x001>;
+ enable-method = "psci";
+ };
+ cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72", "arm,armv8";
+ reg = <0x100>;
+ enable-method = "psci";
+ };
+ cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72", "arm,armv8";
+ reg = <0x101>;
+ enable-method = "psci";
+ };
+ };
+};
diff --git a/arch/arm/dts/armada-ap806.dtsi b/arch/arm/dts/armada-ap806.dtsi
new file mode 100644
index 0000000000..d315b29cd0
--- /dev/null
+++ b/arch/arm/dts/armada-ap806.dtsi
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2016 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Device Tree file for Marvell Armada AP806.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/dts-v1/;
+
+/ {
+ model = "Marvell Armada AP806";
+ compatible = "marvell,armada-ap806";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ };
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ ap806 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ config-space {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x0 0x0 0xf0000000 0x1000000>;
+
+ gic: interrupt-controller@210000 {
+ compatible = "arm,gic-400";
+ #interrupt-cells = <3>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ interrupt-controller;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ reg = <0x210000 0x10000>,
+ <0x220000 0x20000>,
+ <0x240000 0x20000>,
+ <0x260000 0x20000>;
+
+ gic_v2m0: v2m@280000 {
+ compatible = "arm,gic-v2m-frame";
+ msi-controller;
+ reg = <0x280000 0x1000>;
+ arm,msi-base-spi = <160>;
+ arm,msi-num-spis = <32>;
+ };
+ gic_v2m1: v2m@290000 {
+ compatible = "arm,gic-v2m-frame";
+ msi-controller;
+ reg = <0x290000 0x1000>;
+ arm,msi-base-spi = <192>;
+ arm,msi-num-spis = <32>;
+ };
+ gic_v2m2: v2m@2a0000 {
+ compatible = "arm,gic-v2m-frame";
+ msi-controller;
+ reg = <0x2a0000 0x1000>;
+ arm,msi-base-spi = <224>;
+ arm,msi-num-spis = <32>;
+ };
+ gic_v2m3: v2m@2b0000 {
+ compatible = "arm,gic-v2m-frame";
+ msi-controller;
+ reg = <0x2b0000 0x1000>;
+ arm,msi-base-spi = <256>;
+ arm,msi-num-spis = <32>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
+ };
+
+ odmi: odmi@300000 {
+ compatible = "marvell,odmi-controller";
+ interrupt-controller;
+ msi-controller;
+ marvell,odmi-frames = <4>;
+ reg = <0x300000 0x4000>,
+ <0x304000 0x4000>,
+ <0x308000 0x4000>,
+ <0x30C000 0x4000>;
+ marvell,spi-base = <128>, <136>, <144>, <152>;
+ };
+
+ xor@400000 {
+ compatible = "marvell,mv-xor-v2";
+ reg = <0x400000 0x1000>,
+ <0x410000 0x1000>;
+ msi-parent = <&gic_v2m0>;
+ dma-coherent;
+ };
+
+ xor@420000 {
+ compatible = "marvell,mv-xor-v2";
+ reg = <0x420000 0x1000>,
+ <0x430000 0x1000>;
+ msi-parent = <&gic_v2m0>;
+ dma-coherent;
+ };
+
+ xor@440000 {
+ compatible = "marvell,mv-xor-v2";
+ reg = <0x440000 0x1000>,
+ <0x450000 0x1000>;
+ msi-parent = <&gic_v2m0>;
+ dma-coherent;
+ };
+
+ xor@460000 {
+ compatible = "marvell,mv-xor-v2";
+ reg = <0x460000 0x1000>,
+ <0x470000 0x1000>;
+ msi-parent = <&gic_v2m0>;
+ dma-coherent;
+ };
+
+ spi0: spi@510600 {
+ compatible = "marvell,armada-380-spi";
+ reg = <0x510600 0x50>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ap_syscon 3>;
+ status = "disabled";
+ };
+
+ i2c0: i2c@511000 {
+ compatible = "marvell,mv78230-i2c";
+ reg = <0x511000 0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ timeout-ms = <1000>;
+ clocks = <&ap_syscon 3>;
+ status = "disabled";
+ };
+
+ uart0: serial@512000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x512000 0x100>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ reg-io-width = <1>;
+ clocks = <&ap_syscon 3>;
+ status = "disabled";
+ clock-frequency = <200000000>;
+ };
+
+ uart1: serial@512100 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x512100 0x100>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ reg-io-width = <1>;
+ clocks = <&ap_syscon 3>;
+ status = "disabled";
+
+ };
+
+ ap_syscon: system-controller@6f4000 {
+ compatible = "marvell,ap806-system-controller",
+ "syscon";
+ #clock-cells = <1>;
+ clock-output-names = "ap-cpu-cluster-0",
+ "ap-cpu-cluster-1",
+ "ap-fixed", "ap-mss";
+ reg = <0x6f4000 0x1000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi
new file mode 100644
index 0000000000..7da98bf5cb
--- /dev/null
+++ b/arch/arm/dts/armada-cp110-master.dtsi
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2016 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Device Tree file for Marvell Armada CP110 Master.
+ */
+
+#include <dt-bindings/comphy/comphy_data.h>
+
+/ {
+ cp110-master {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ config-space {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges = <0x0 0x0 0xf2000000 0x2000000>;
+
+ cpm_syscon0: system-controller@440000 {
+ compatible = "marvell,cp110-system-controller0",
+ "syscon";
+ reg = <0x440000 0x1000>;
+ #clock-cells = <2>;
+ core-clock-output-names =
+ "cpm-apll", "cpm-ppv2-core", "cpm-eip",
+ "cpm-core", "cpm-nand-core";
+ gate-clock-output-names =
+ "cpm-audio", "cpm-communit", "cpm-nand",
+ "cpm-ppv2", "cpm-sdio", "cpm-mg-domain",
+ "cpm-mg-core", "cpm-xor1", "cpm-xor0",
+ "cpm-gop-dp", "none", "cpm-pcie_x10",
+ "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor",
+ "cpm-sata", "cpm-sata-usb", "cpm-main",
+ "cpm-sd-mmc", "none", "none",
+ "cpm-slow-io", "cpm-usb3h0", "cpm-usb3h1",
+ "cpm-usb3dev", "cpm-eip150", "cpm-eip197";
+ };
+
+ cpm_sata0: sata@540000 {
+ compatible = "marvell,armada-8k-ahci";
+ reg = <0x540000 0x30000>;
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpm_syscon0 1 15>;
+ status = "disabled";
+ };
+
+ cpm_usb3_0: usb3@500000 {
+ compatible = "marvell,armada-8k-xhci",
+ "generic-xhci";
+ reg = <0x500000 0x4000>;
+ dma-coherent;
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpm_syscon0 1 22>;
+ status = "disabled";
+ };
+
+ cpm_usb3_1: usb3@510000 {
+ compatible = "marvell,armada-8k-xhci",
+ "generic-xhci";
+ reg = <0x510000 0x4000>;
+ dma-coherent;
+ interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpm_syscon0 1 23>;
+ status = "disabled";
+ };
+
+ cpm_spi0: spi@700600 {
+ compatible = "marvell,armada-380-spi";
+ reg = <0x700600 0x50>;
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ cell-index = <1>;
+ clocks = <&cpm_syscon0 0 3>;
+ status = "disabled";
+ };
+
+ cpm_spi1: spi@700680 {
+ compatible = "marvell,armada-380-spi";
+ reg = <0x700680 0x50>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <2>;
+ clocks = <&cpm_syscon0 1 21>;
+ status = "disabled";
+ };
+
+ cpm_i2c0: i2c@701000 {
+ compatible = "marvell,mv78230-i2c";
+ reg = <0x701000 0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpm_syscon0 1 21>;
+ status = "disabled";
+ };
+
+ cpm_i2c1: i2c@701100 {
+ compatible = "marvell,mv78230-i2c";
+ reg = <0x701100 0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpm_syscon0 1 21>;
+ status = "disabled";
+ };
+
+ comphy_cp110: comphy@441000 {
+ compatible = "marvell,mvebu-comphy", "marvell,comphy-cp110";
+ reg = <0x441000 0x8>,
+ <0x120000 0x8>;
+ mux-bitcount = <4>;
+ max-lanes = <6>;
+ };
+
+ utmi0: utmi@580000 {
+ compatible = "marvell,mvebu-utmi-2.6.0";
+ reg = <0x580000 0x1000>, /* utmi-unit */
+ <0x440420 0x4>, /* usb-cfg */
+ <0x440440 0x4>; /* utmi-cfg */
+ utmi-port = <UTMI_PHY_TO_USB_HOST0>;
+ status = "disabled";
+ };
+
+ utmi1: utmi@581000 {
+ compatible = "marvell,mvebu-utmi-2.6.0";
+ reg = <0x581000 0x1000>, /* utmi-unit */
+ <0x440420 0x4>, /* usb-cfg */
+ <0x440444 0x4>; /* utmi-cfg */
+ utmi-port = <UTMI_PHY_TO_USB_HOST1>;
+ status = "disabled";
+ };
+ };
+
+ cpm_pcie0: pcie@f2600000 {
+ compatible = "marvell,armada8k-pcie", "snps,dw-pcie";
+ reg = <0 0xf2600000 0 0x10000>,
+ <0 0xf6f00000 0 0x80000>;
+ reg-names = "ctrl", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ dma-coherent;
+
+ bus-range = <0 0xff>;
+ ranges =
+ /* downstream I/O */
+ <0x81000000 0 0xf9000000 0 0xf9000000 0 0x10000
+ /* non-prefetchable memory */
+ 0x82000000 0 0xf6000000 0 0xf6000000 0 0xf00000>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ num-lanes = <1>;
+ clocks = <&cpm_syscon0 1 13>;
+ status = "disabled";
+ };
+
+ cpm_pcie1: pcie@f2620000 {
+ compatible = "marvell,armada8k-pcie", "snps,dw-pcie";
+ reg = <0 0xf2620000 0 0x10000>,
+ <0 0xf7f00000 0 0x80000>;
+ reg-names = "ctrl", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ dma-coherent;
+
+ bus-range = <0 0xff>;
+ ranges =
+ /* downstream I/O */
+ <0x81000000 0 0xf9010000 0 0xf9010000 0 0x10000
+ /* non-prefetchable memory */
+ 0x82000000 0 0xf7000000 0 0xf7000000 0 0xf00000>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+
+ num-lanes = <1>;
+ clocks = <&cpm_syscon0 1 11>;
+ status = "disabled";
+ };
+
+ cpm_pcie2: pcie@f2640000 {
+ compatible = "marvell,armada8k-pcie", "snps,dw-pcie";
+ reg = <0 0xf2640000 0 0x10000>,
+ <0 0xf8f00000 0 0x80000>;
+ reg-names = "ctrl", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ dma-coherent;
+
+ bus-range = <0 0xff>;
+ ranges =
+ /* downstream I/O */
+ <0x81000000 0 0xf9020000 0 0xf9020000 0 0x10000
+ /* non-prefetchable memory */
+ 0x82000000 0 0xf8000000 0 0xf8000000 0 0xf00000>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+
+ num-lanes = <1>;
+ clocks = <&cpm_syscon0 1 12>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 0fd71a717a..6e8026bde2 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -1,14 +1,42 @@
if ARCH_MVEBU
+config ARMADA_32BIT
+ bool
+ select CPU_V7
+ select SUPPORT_SPL
+ select SPL_DM
+ select SPL_DM_SEQ_ALIAS
+ select SPL_OF_CONTROL
+ select SPL_SIMPLE_BUS
+
+config ARMADA_64BIT
+ bool
+ select ARM64
+
+# ARMv7 SoCs...
config ARMADA_375
bool
+ select ARMADA_32BIT
config ARMADA_38X
bool
+ select ARMADA_32BIT
config ARMADA_XP
bool
+ select ARMADA_32BIT
+
+# ARMv8 SoCs...
+config ARMADA_3700
+ bool
+ select ARM64
+# Armada 7K and 8K are very similar - use only one Kconfig symbol for both
+config ARMADA_8K
+ bool
+ select ARM64
+
+# Armada XP/38x SoC types...
config MV78230
bool
select ARMADA_XP
@@ -26,13 +54,17 @@ config 88F6820
select ARMADA_38X
choice
- prompt "Marvell MVEBU (Armada XP/375/38x) board select"
+ prompt "Armada XP/375/38x/3700/7K/8K board select"
optional
config TARGET_CLEARFOG
bool "Support ClearFog"
select 88F6820
+config TARGET_MVEBU_DB_88F3720
+ bool "Support DB-88F3720 Armada 3720"
+ select ARMADA_3700
+
config TARGET_DB_88F6720
bool "Support DB-88F6720 Armada 375"
select ARMADA_375
@@ -45,6 +77,10 @@ config TARGET_DB_88F6820_AMC
bool "Support DB-88F6820-AMC"
select 88F6820
+config TARGET_MVEBU_DB_88F7040
+ bool "Support DB-88F7040 Armada 7040"
+ select ARMADA_8K
+
config TARGET_DB_MV784MP_GP
bool "Support db-mv784mp-gp"
select MV78460
@@ -65,9 +101,11 @@ endchoice
config SYS_BOARD
default "clearfog" if TARGET_CLEARFOG
+ default "mvebu_db-88f3720" if TARGET_MVEBU_DB_88F3720
default "db-88f6720" if TARGET_DB_88F6720
default "db-88f6820-gp" if TARGET_DB_88F6820_GP
default "db-88f6820-amc" if TARGET_DB_88F6820_AMC
+ default "mvebu_db-88f7040" if TARGET_MVEBU_DB_88F7040
default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP
default "ds414" if TARGET_DS414
default "maxbcm" if TARGET_MAXBCM
@@ -75,9 +113,11 @@ config SYS_BOARD
config SYS_CONFIG_NAME
default "clearfog" if TARGET_CLEARFOG
+ default "mvebu_db-88f3720" if TARGET_MVEBU_DB_88F3720
default "db-88f6720" if TARGET_DB_88F6720
default "db-88f6820-gp" if TARGET_DB_88F6820_GP
default "db-88f6820-amc" if TARGET_DB_88F6820_AMC
+ default "mvebu_db-88f7040" if TARGET_MVEBU_DB_88F7040
default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP
default "ds414" if TARGET_DS414
default "maxbcm" if TARGET_MAXBCM
@@ -85,9 +125,11 @@ config SYS_CONFIG_NAME
config SYS_VENDOR
default "Marvell" if TARGET_DB_MV784MP_GP
+ default "Marvell" if TARGET_MVEBU_DB_88F3720
default "Marvell" if TARGET_DB_88F6720
default "Marvell" if TARGET_DB_88F6820_GP
default "Marvell" if TARGET_DB_88F6820_AMC
+ default "Marvell" if TARGET_MVEBU_DB_88F7040
default "solidrun" if TARGET_CLEARFOG
default "Synology" if TARGET_DS414
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index ac009a36da..65e90c4fc9 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -1,16 +1,25 @@
#
-# Copyright (C) 2014-2015 Stefan Roese <sr@denx.de>
+# Copyright (C) 2014-2016 Stefan Roese <sr@denx.de>
#
# SPDX-License-Identifier: GPL-2.0+
#
+ifdef CONFIG_ARM64
+
+obj-$(CONFIG_ARMADA_3700) += armada3700/
+obj-$(CONFIG_ARMADA_8K) += armada8k/
+obj-y += arm64-common.o
+obj-y += sata.o
+
+else # CONFIG_ARM64
+
ifdef CONFIG_KIRKWOOD
obj-y = dram.o
obj-y += gpio.o
obj-y += timer.o
-else
+else # CONFIG_KIRKWOOD
obj-y = cpu.o
obj-y += dram.o
@@ -18,7 +27,7 @@ ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o
obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
-endif
+endif # CONFIG_SPL_BUILD
obj-y += gpio.o
obj-y += mbus.o
obj-y += timer.o
@@ -28,4 +37,5 @@ obj-$(CONFIG_SPL_BUILD) += lowlevel_spl.o
obj-$(CONFIG_ARMADA_38X) += serdes/a38x/
obj-$(CONFIG_ARMADA_XP) += serdes/axp/
-endif
+endif # CONFIG_KIRKWOOD
+endif # CONFIG_ARM64
diff --git a/arch/arm/mach-mvebu/arm64-common.c b/arch/arm/mach-mvebu/arm64-common.c
new file mode 100644
index 0000000000..7055a81de3
--- /dev/null
+++ b/arch/arm/mach-mvebu/arm64-common.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <asm/armv8/mmu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * On ARMv8, MBus is not configured in U-Boot. To enable compilation
+ * of the already implemented drivers, lets add a dummy version of
+ * this function so that linking does not fail.
+ */
+const struct mbus_dram_target_info *mvebu_mbus_dram_info(void)
+{
+ return NULL;
+}
+
+/* DRAM init code ... */
+
+static const void *get_memory_reg_prop(const void *fdt, int *lenp)
+{
+ int offset;
+
+ offset = fdt_path_offset(fdt, "/memory");
+ if (offset < 0)
+ return NULL;
+
+ return fdt_getprop(fdt, offset, "reg", lenp);
+}
+
+int dram_init(void)
+{
+ const void *fdt = gd->fdt_blob;
+ const fdt32_t *val;
+ int ac, sc, len;
+
+ ac = fdt_address_cells(fdt, 0);
+ sc = fdt_size_cells(fdt, 0);
+ if (ac < 0 || sc < 1 || sc > 2) {
+ printf("invalid address/size cells\n");
+ return -EINVAL;
+ }
+
+ val = get_memory_reg_prop(fdt, &len);
+ if (len / sizeof(*val) < ac + sc)
+ return -EINVAL;
+
+ val += ac;
+
+ gd->ram_size = fdtdec_get_number(val, sc);
+
+ debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size);
+
+ return 0;
+}
+
+void dram_init_banksize(void)
+{
+ const void *fdt = gd->fdt_blob;
+ const fdt32_t *val;
+ int ac, sc, cells, len, i;
+
+ val = get_memory_reg_prop(fdt, &len);
+ if (len < 0)
+ return;
+
+ ac = fdt_address_cells(fdt, 0);
+ sc = fdt_size_cells(fdt, 0);
+ if (ac < 1 || sc > 2 || sc < 1 || sc > 2) {
+ printf("invalid address/size cells\n");
+ return;
+ }
+
+ cells = ac + sc;
+
+ len /= sizeof(*val);
+
+ for (i = 0; i < CONFIG_NR_DRAM_BANKS && len >= cells;
+ i++, len -= cells) {
+ gd->bd->bi_dram[i].start = fdtdec_get_number(val, ac);
+ val += ac;
+ gd->bd->bi_dram[i].size = fdtdec_get_number(val, sc);
+ val += sc;
+
+ debug("DRAM bank %d: start = %08lx, size = %08lx\n",
+ i, (unsigned long)gd->bd->bi_dram[i].start,
+ (unsigned long)gd->bd->bi_dram[i].size);
+ }
+}
+
+int arch_cpu_init(void)
+{
+ /* Nothing to do (yet) */
+ return 0;
+}
+
+int arch_early_init_r(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ /* Call the comphy code via the MISC uclass driver */
+ ret = uclass_get_device(UCLASS_MISC, 0, &dev);
+ if (ret) {
+ debug("COMPHY init failed: %d\n", ret);
+ return -ENODEV;
+ }
+
+ /* Cause the SATA device to do its early init */
+ uclass_first_device(UCLASS_AHCI, &dev);
+
+ return 0;
+}
diff --git a/arch/arm/mach-mvebu/armada3700/Makefile b/arch/arm/mach-mvebu/armada3700/Makefile
new file mode 100644
index 0000000000..84c69d90e7
--- /dev/null
+++ b/arch/arm/mach-mvebu/armada3700/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2016 Stefan Roese <sr@denx.de>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y = cpu.o
diff --git a/arch/arm/mach-mvebu/armada3700/cpu.c b/arch/arm/mach-mvebu/armada3700/cpu.c
new file mode 100644
index 0000000000..6499eec4ea
--- /dev/null
+++ b/arch/arm/mach-mvebu/armada3700/cpu.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <asm/armv8/mmu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Armada 3700 */
+#define MVEBU_GPIO_NB_REG_BASE (MVEBU_REGISTER(0x13800))
+
+#define MVEBU_TEST_PIN_LATCH_N (MVEBU_GPIO_NB_REG_BASE + 0x8)
+#define MVEBU_XTAL_MODE_MASK BIT(9)
+#define MVEBU_XTAL_MODE_OFFS 9
+#define MVEBU_XTAL_CLOCK_25MHZ 0x0
+#define MVEBU_XTAL_CLOCK_40MHZ 0x1
+
+#define MVEBU_NB_WARM_RST_REG (MVEBU_GPIO_NB_REG_BASE + 0x40)
+#define MVEBU_NB_WARM_RST_MAGIC_NUM 0x1d1e
+
+static struct mm_region mvebu_mem_map[] = {
+ {
+ /* RAM */
+ .phys = 0x0UL,
+ .virt = 0x0UL,
+ .size = 0x80000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ },
+ {
+ /* SRAM, MMIO regions */
+ .phys = 0xd0000000UL,
+ .virt = 0xd0000000UL,
+ .size = 0x02000000UL, /* 32MiB internal registers */
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE
+ },
+ {
+ /* List terminator */
+ 0,
+ }
+};
+
+struct mm_region *mem_map = mvebu_mem_map;
+
+void reset_cpu(ulong ignored)
+{
+ /*
+ * Write magic number of 0x1d1e to North Bridge Warm Reset register
+ * to trigger warm reset
+ */
+ writel(MVEBU_NB_WARM_RST_MAGIC_NUM, MVEBU_NB_WARM_RST_REG);
+}
+
+/*
+ * get_ref_clk
+ *
+ * return: reference clock in MHz (25 or 40)
+ */
+u32 get_ref_clk(void)
+{
+ u32 regval;
+
+ regval = (readl(MVEBU_TEST_PIN_LATCH_N) & MVEBU_XTAL_MODE_MASK) >>
+ MVEBU_XTAL_MODE_OFFS;
+
+ if (regval == MVEBU_XTAL_CLOCK_25MHZ)
+ return 25;
+ else
+ return 40;
+}
diff --git a/arch/arm/mach-mvebu/armada8k/Makefile b/arch/arm/mach-mvebu/armada8k/Makefile
new file mode 100644
index 0000000000..84c69d90e7
--- /dev/null
+++ b/arch/arm/mach-mvebu/armada8k/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2016 Stefan Roese <sr@denx.de>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y = cpu.o
diff --git a/arch/arm/mach-mvebu/armada8k/cpu.c b/arch/arm/mach-mvebu/armada8k/cpu.c
new file mode 100644
index 0000000000..036430c46c
--- /dev/null
+++ b/arch/arm/mach-mvebu/armada8k/cpu.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <asm/armv8/mmu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Armada 7k/8k */
+#define MVEBU_RFU_BASE (MVEBU_REGISTER(0x6f0000))
+#define RFU_GLOBAL_SW_RST (MVEBU_RFU_BASE + 0x84)
+#define RFU_SW_RESET_OFFSET 0
+
+static struct mm_region mvebu_mem_map[] = {
+ {
+ /* RAM */
+ .phys = 0x0UL,
+ .virt = 0x0UL,
+ .size = 0x80000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ },
+ {
+ /* SRAM, MMIO regions - AP806 region */
+ .phys = 0xf0000000UL,
+ .virt = 0xf0000000UL,
+ .size = 0x01000000UL, /* 16MiB internal registers */
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE
+ },
+ {
+ /* SRAM, MMIO regions - CP110 region */
+ .phys = 0xf2000000UL,
+ .virt = 0xf2000000UL,
+ .size = 0x02000000UL, /* 32MiB internal registers */
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE
+ },
+ {
+ /* List terminator */
+ 0,
+ }
+};
+
+struct mm_region *mem_map = mvebu_mem_map;
+
+void reset_cpu(ulong ignored)
+{
+ u32 reg;
+
+ reg = readl(RFU_GLOBAL_SW_RST);
+ reg &= ~(1 << RFU_SW_RESET_OFFSET);
+ writel(reg, RFU_GLOBAL_SW_RST);
+}
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index cbec876c42..66f7680fb3 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -166,5 +166,12 @@ struct mvebu_lcd_info {
int mvebu_lcd_register_init(struct mvebu_lcd_info *lcd_info);
+/*
+ * get_ref_clk
+ *
+ * return: reference clock in MHz (25 or 40)
+ */
+u32 get_ref_clk(void);
+
#endif /* __ASSEMBLY__ */
#endif /* _MVEBU_CPU_H */
diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
index 6342cdc35c..731fe65ae4 100644
--- a/arch/arm/mach-mvebu/include/mach/soc.h
+++ b/arch/arm/mach-mvebu/include/mach/soc.h
@@ -37,7 +37,7 @@
/* SOC specific definations */
#define INTREG_BASE 0xd0000000
#define INTREG_BASE_ADDR_REG (INTREG_BASE + 0x20080)
-#if defined(CONFIG_SPL_BUILD)
+#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_ARMADA_3700)
/*
* The SPL U-Boot version still runs with the default
* address for the internal registers, configured by
@@ -46,6 +46,8 @@
* required for the Linux kernel.
*/
#define SOC_REGS_PHY_BASE 0xd0000000
+#elif defined(CONFIG_ARMADA_8K)
+#define SOC_REGS_PHY_BASE 0xf0000000
#else
#define SOC_REGS_PHY_BASE 0xf1000000
#endif
diff --git a/arch/arm/mach-mvebu/sata.c b/arch/arm/mach-mvebu/sata.c
new file mode 100644
index 0000000000..140a2952c3
--- /dev/null
+++ b/arch/arm/mach-mvebu/sata.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <ahci.h>
+#include <dm.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Dummy implementation that can be overwritten by a board
+ * specific function
+ */
+__weak int board_ahci_enable(void)
+{
+ return 0;
+}
+
+#ifdef CONFIG_ARMADA_8K
+/* CP110 has different AHCI port addresses */
+void __iomem *ahci_port_base(void __iomem *base, u32 port)
+{
+ return base + 0x10000 + (port * 0x10000);
+}
+#endif
+
+static int mvebu_ahci_probe(struct udevice *dev)
+{
+ /*
+ * Board specific SATA / AHCI enable code, e.g. enable the
+ * AHCI power or deassert reset
+ */
+ board_ahci_enable();
+
+ ahci_init(dev_get_addr_ptr(dev));
+
+ return 0;
+}
+
+static const struct udevice_id mvebu_ahci_ids[] = {
+ { .compatible = "marvell,armada-3700-ahci" },
+ { .compatible = "marvell,armada-8k-ahci" },
+ { }
+};
+
+U_BOOT_DRIVER(ahci_mvebu_drv) = {
+ .name = "ahci_mvebu",
+ .id = UCLASS_AHCI,
+ .of_match = mvebu_ahci_ids,
+ .probe = mvebu_ahci_probe,
+};
diff --git a/board/Marvell/mvebu_db-88f3720/MAINTAINERS b/board/Marvell/mvebu_db-88f3720/MAINTAINERS
new file mode 100644
index 0000000000..4e80917c72
--- /dev/null
+++ b/board/Marvell/mvebu_db-88f3720/MAINTAINERS
@@ -0,0 +1,6 @@
+MVEBU_DB_88F3720 BOARD
+M: Stefan Roese <sr@denx.de>
+S: Maintained
+F: board/Marvell/mvebu_db-88f3720/
+F: include/configs/mvebu_db-88f3720.h
+F: configs/mvebu_db-88f3720_defconfig
diff --git a/board/Marvell/mvebu_db-88f3720/Makefile b/board/Marvell/mvebu_db-88f3720/Makefile
new file mode 100644
index 0000000000..ed39738816
--- /dev/null
+++ b/board/Marvell/mvebu_db-88f3720/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2016 Stefan Roese <sr@denx.de>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y := board.o
diff --git a/board/Marvell/mvebu_db-88f3720/board.c b/board/Marvell/mvebu_db-88f3720/board.c
new file mode 100644
index 0000000000..edf88c73e6
--- /dev/null
+++ b/board/Marvell/mvebu_db-88f3720/board.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* IO expander I2C device */
+#define I2C_IO_EXP_ADDR 0x22
+#define I2C_IO_CFG_REG_0 0x6
+#define I2C_IO_DATA_OUT_REG_0 0x2
+#define I2C_IO_REG_0_SATA_OFF 2
+#define I2C_IO_REG_0_USB_H_OFF 1
+
+int board_early_init_f(void)
+{
+ /* Nothing to do (yet), perhaps later some pin-muxing etc */
+
+ return 0;
+}
+
+int board_init(void)
+{
+ /* adress of boot parameters */
+ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+ return 0;
+}
+
+/* Board specific AHCI / SATA enable code */
+int board_ahci_enable(void)
+{
+ struct udevice *dev;
+ int ret;
+ u8 buf[8];
+
+ /* Configure IO exander PCA9555: 7bit address 0x22 */
+ ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
+ if (ret) {
+ printf("Cannot find PCA9555: %d\n", ret);
+ return 0;
+ }
+
+ ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to read IO expander value via I2C\n");
+ return -EIO;
+ }
+
+ /*
+ * Enable SATA power via IO expander connected via I2C by setting
+ * the corresponding bit to output mode to enable power for SATA
+ */
+ buf[0] &= ~(1 << I2C_IO_REG_0_SATA_OFF);
+ ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to set IO expander via I2C\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/* Board specific xHCI enable code */
+int board_xhci_enable(void)
+{
+ struct udevice *dev;
+ int ret;
+ u8 buf[8];
+
+ /* Configure IO exander PCA9555: 7bit address 0x22 */
+ ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
+ if (ret) {
+ printf("Cannot find PCA9555: %d\n", ret);
+ return 0;
+ }
+
+ printf("Enable USB VBUS\n");
+
+ /*
+ * Read configuration (direction) and set VBUS pin as output
+ * (reset pin = output)
+ */
+ ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to read IO expander value via I2C\n");
+ return -EIO;
+ }
+ buf[0] &= ~(1 << I2C_IO_REG_0_USB_H_OFF);
+ ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to set IO expander via I2C\n");
+ return -EIO;
+ }
+
+ /* Read VBUS output value and disable it */
+ ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to read IO expander value via I2C\n");
+ return -EIO;
+ }
+ buf[0] &= ~(1 << I2C_IO_REG_0_USB_H_OFF);
+ ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to set IO expander via I2C\n");
+ return -EIO;
+ }
+
+ /*
+ * Required delay for configuration to settle - must wait for
+ * power on port is disabled in case VBUS signal was high,
+ * required 3 seconds delay to let VBUS signal fully settle down
+ */
+ mdelay(3000);
+
+ /* Enable VBUS power: Set output value of VBUS pin as enabled */
+ buf[0] |= (1 << I2C_IO_REG_0_USB_H_OFF);
+ ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to set IO expander via I2C\n");
+ return -EIO;
+ }
+
+ mdelay(500); /* required delay to let output value settle */
+
+ return 0;
+}
diff --git a/board/Marvell/mvebu_db-88f7040/MAINTAINERS b/board/Marvell/mvebu_db-88f7040/MAINTAINERS
new file mode 100644
index 0000000000..820461b213
--- /dev/null
+++ b/board/Marvell/mvebu_db-88f7040/MAINTAINERS
@@ -0,0 +1,6 @@
+MVEBU_DB_88F7040 BOARD
+M: Stefan Roese <sr@denx.de>
+S: Maintained
+F: board/Marvell/mvebu_db-88f7040/
+F: include/configs/mvebu_db-88f7040.h
+F: configs/mvebu_db-88f7040_defconfig
diff --git a/board/Marvell/mvebu_db-88f7040/Makefile b/board/Marvell/mvebu_db-88f7040/Makefile
new file mode 100644
index 0000000000..ed39738816
--- /dev/null
+++ b/board/Marvell/mvebu_db-88f7040/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2016 Stefan Roese <sr@denx.de>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y := board.o
diff --git a/board/Marvell/mvebu_db-88f7040/board.c b/board/Marvell/mvebu_db-88f7040/board.c
new file mode 100644
index 0000000000..48bd55c372
--- /dev/null
+++ b/board/Marvell/mvebu_db-88f7040/board.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* IO expander I2C device */
+#define I2C_IO_EXP_ADDR 0x21
+#define I2C_IO_CFG_REG_0 0x6
+#define I2C_IO_DATA_OUT_REG_0 0x2
+/* VBus enable */
+#define I2C_IO_REG_0_USB_H0_OFF 0
+#define I2C_IO_REG_0_USB_H1_OFF 1
+#define I2C_IO_REG_VBUS ((1 << I2C_IO_REG_0_USB_H0_OFF) | \
+ (1 << I2C_IO_REG_0_USB_H1_OFF))
+/* Current limit */
+#define I2C_IO_REG_0_USB_H0_CL 4
+#define I2C_IO_REG_0_USB_H1_CL 5
+#define I2C_IO_REG_CL ((1 << I2C_IO_REG_0_USB_H0_CL) | \
+ (1 << I2C_IO_REG_0_USB_H1_CL))
+
+static int usb_enabled = 0;
+
+/* Board specific xHCI dis-/enable code */
+
+/*
+ * Set USB VBUS signals (via I2C IO expander/GPIO) as output and set
+ * output value as disabled
+ *
+ * Set USB Current Limit signals (via I2C IO expander/GPIO) as output
+ * and set output value as enabled
+ */
+int board_xhci_config(void)
+{
+ struct udevice *dev;
+ int ret;
+ u8 buf[8];
+
+ /* Configure IO exander PCA9555: 7bit address 0x21 */
+ ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
+ if (ret) {
+ printf("Cannot find PCA9555: %d\n", ret);
+ return 0;
+ }
+
+ /*
+ * Read configuration (direction) and set VBUS pin as output
+ * (reset pin = output)
+ */
+ ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to read IO expander value via I2C\n");
+ return -EIO;
+ }
+ buf[0] &= ~I2C_IO_REG_VBUS;
+ buf[0] &= ~I2C_IO_REG_CL;
+ ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to set IO expander via I2C\n");
+ return -EIO;
+ }
+
+ /* Read output value and configure it */
+ ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to read IO expander value via I2C\n");
+ return -EIO;
+ }
+ buf[0] &= ~I2C_IO_REG_VBUS;
+ buf[0] |= I2C_IO_REG_CL;
+ ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to set IO expander via I2C\n");
+ return -EIO;
+ }
+
+ mdelay(500); /* required delay to let output value settle */
+
+ return 0;
+}
+
+int board_xhci_enable(void)
+{
+ struct udevice *dev;
+ int ret;
+ u8 buf[8];
+
+ /*
+ * This function enables all USB ports simultaniously,
+ * it only needs to get called once
+ */
+ if (usb_enabled)
+ return 0;
+
+ /* Configure IO exander PCA9555: 7bit address 0x21 */
+ ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
+ if (ret) {
+ printf("Cannot find PCA9555: %d\n", ret);
+ return 0;
+ }
+
+ /* Read VBUS output value */
+ ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to read IO expander value via I2C\n");
+ return -EIO;
+ }
+
+ /* Enable VBUS power: Set output value of VBUS pin as enabled */
+ buf[0] |= I2C_IO_REG_VBUS;
+ ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
+ if (ret) {
+ printf("Failed to set IO expander via I2C\n");
+ return -EIO;
+ }
+
+ mdelay(500); /* required delay to let output value settle */
+ usb_enabled = 1;
+
+ return 0;
+}
+
+int board_early_init_f(void)
+{
+ /* Nothing to do (yet), perhaps later some pin-muxing etc */
+
+ return 0;
+}
+
+int board_init(void)
+{
+ /* adress of boot parameters */
+ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+ return 0;
+}
+
+int board_late_init(void)
+{
+ /* Pre-configure the USB ports (overcurrent, VBus) */
+ board_xhci_config();
+
+ return 0;
+}
diff --git a/configs/mvebu_db-88f3720_defconfig b/configs/mvebu_db-88f3720_defconfig
new file mode 100644
index 0000000000..813d0645d3
--- /dev/null
+++ b/configs/mvebu_db-88f3720_defconfig
@@ -0,0 +1,49 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_TARGET_MVEBU_DB_88F3720=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-3720-db"
+CONFIG_AHCI=y
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_FPGA is not set
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_BLOCK_CACHE=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_MISC=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_PHYLIB=y
+CONFIG_MVEBU_COMPHY_SUPPORT=y
+# CONFIG_SPL_SERIAL_PRESENT is not set
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_MVEBU_A3700_UART=y
+CONFIG_DEBUG_UART_BASE=0xd0012000
+CONFIG_DEBUG_UART_CLOCK=25804800
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_MVEBU_A3700_UART=y
+CONFIG_MVEBU_A3700_SPI=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
diff --git a/configs/mvebu_db-88f7040_defconfig b/configs/mvebu_db-88f7040_defconfig
new file mode 100644
index 0000000000..4d68bdc7bb
--- /dev/null
+++ b/configs/mvebu_db-88f7040_defconfig
@@ -0,0 +1,47 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_TARGET_MVEBU_DB_88F7040=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-7040-db"
+CONFIG_AHCI=y
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_FPGA is not set
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_BLOCK_CACHE=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MVTWSI=y
+CONFIG_MISC=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_PHYLIB=y
+CONFIG_MVEBU_COMPHY_SUPPORT=y
+# CONFIG_SPL_SERIAL_PRESENT is not set
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xf0512000
+CONFIG_DEBUG_UART_CLOCK=200000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_SYS_NS16550=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 4c555a0c1f..e8c9e0a326 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -48,6 +48,8 @@ source "drivers/pci/Kconfig"
source "drivers/pcmcia/Kconfig"
+source "drivers/phy/marvell/Kconfig"
+
source "drivers/pinctrl/Kconfig"
source "drivers/power/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index ca98273134..761d0b3e85 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -70,6 +70,7 @@ obj-y += misc/
obj-y += pcmcia/
obj-y += dfu/
obj-$(CONFIG_X86) += pch/
+obj-y += phy/marvell/
obj-y += rtc/
obj-y += sound/
obj-y += spmi/
diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c
index 2e1ddf9dac..5139989d0b 100644
--- a/drivers/block/ahci.c
+++ b/drivers/block/ahci.c
@@ -45,7 +45,7 @@ u16 *ataid[AHCI_MAX_PORTS];
#define WAIT_MS_FLUSH 5000
#define WAIT_MS_LINKUP 200
-static inline void __iomem *ahci_port_base(void __iomem *base, u32 port)
+__weak void __iomem *ahci_port_base(void __iomem *base, u32 port)
{
return base + 0x100 + (port * 0x80);
}
diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index 6d51b9f0c0..51bb569a92 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -91,7 +91,11 @@ DECLARE_GLOBAL_DATA_PTR;
#define MVNETA_WIN_BASE(w) (0x2200 + ((w) << 3))
#define MVNETA_WIN_SIZE(w) (0x2204 + ((w) << 3))
#define MVNETA_WIN_REMAP(w) (0x2280 + ((w) << 2))
+#define MVNETA_WIN_SIZE_MASK (0xffff0000)
#define MVNETA_BASE_ADDR_ENABLE 0x2290
+#define MVNETA_BASE_ADDR_ENABLE_BIT 0x1
+#define MVNETA_PORT_ACCESS_PROTECT 0x2294
+#define MVNETA_PORT_ACCESS_PROTECT_WIN0_RW 0x3
#define MVNETA_PORT_CONFIG 0x2400
#define MVNETA_UNI_PROMISC_MODE BIT(0)
#define MVNETA_DEF_RXQ(q) ((q) << 1)
@@ -1022,7 +1026,7 @@ static int mvneta_txq_init(struct mvneta_port *pp,
txq->size = pp->tx_ring_size;
/* Allocate memory for TX descriptors */
- txq->descs_phys = (u32)txq->descs;
+ txq->descs_phys = (dma_addr_t)txq->descs;
if (txq->descs == NULL)
return -ENOMEM;
@@ -1241,6 +1245,32 @@ static int mvneta_init2(struct mvneta_port *pp)
}
/* platform glue : initialize decoding windows */
+
+/*
+ * Not like A380, in Armada3700, there are two layers of decode windows for GBE:
+ * First layer is: GbE Address window that resides inside the GBE unit,
+ * Second layer is: Fabric address window which is located in the NIC400
+ * (South Fabric).
+ * To simplify the address decode configuration for Armada3700, we bypass the
+ * first layer of GBE decode window by setting the first window to 4GB.
+ */
+static void mvneta_bypass_mbus_windows(struct mvneta_port *pp)
+{
+ /*
+ * Set window size to 4GB, to bypass GBE address decode, leave the
+ * work to MBUS decode window
+ */
+ mvreg_write(pp, MVNETA_WIN_SIZE(0), MVNETA_WIN_SIZE_MASK);
+
+ /* Enable GBE address decode window 0 by set bit 0 to 0 */
+ clrbits_le32(pp->base + MVNETA_BASE_ADDR_ENABLE,
+ MVNETA_BASE_ADDR_ENABLE_BIT);
+
+ /* Set GBE address decode window 0 to full Access (read or write) */
+ setbits_le32(pp->base + MVNETA_PORT_ACCESS_PROTECT,
+ MVNETA_PORT_ACCESS_PROTECT_WIN0_RW);
+}
+
static void mvneta_conf_mbus_windows(struct mvneta_port *pp)
{
const struct mbus_dram_target_info *dram;
@@ -1504,9 +1534,10 @@ static int mvneta_send(struct udevice *dev, void *packet, int length)
/* Get a descriptor for the first part of the packet */
tx_desc = mvneta_txq_next_desc_get(txq);
- tx_desc->buf_phys_addr = (u32)packet;
+ tx_desc->buf_phys_addr = (u32)(uintptr_t)packet;
tx_desc->data_size = length;
- flush_dcache_range((u32)packet, (u32)packet + length);
+ flush_dcache_range((ulong)packet,
+ (ulong)packet + ALIGN(length, PKTALIGN));
/* First and Last descriptor */
tx_desc->command = MVNETA_TX_L4_CSUM_NOT | MVNETA_TXD_FLZ_DESC;
@@ -1562,7 +1593,7 @@ static int mvneta_recv(struct udevice *dev, int flags, uchar **packetp)
rx_bytes = rx_desc->data_size - 6;
/* give packet to stack - skip on first 2 bytes */
- data = (u8 *)rx_desc->buf_cookie + 2;
+ data = (u8 *)(uintptr_t)rx_desc->buf_cookie + 2;
/*
* No cache invalidation needed here, since the rx_buffer's are
* located in a uncached memory region
@@ -1593,13 +1624,13 @@ static int mvneta_probe(struct udevice *dev)
if (!buffer_loc.tx_descs) {
/* Align buffer area for descs and rx_buffers to 1MiB */
bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE);
- mmu_set_region_dcache_behaviour((u32)bd_space, BD_SPACE,
+ mmu_set_region_dcache_behaviour((phys_addr_t)bd_space, BD_SPACE,
DCACHE_OFF);
buffer_loc.tx_descs = (struct mvneta_tx_desc *)bd_space;
buffer_loc.rx_descs = (struct mvneta_rx_desc *)
- ((u32)bd_space +
+ ((phys_addr_t)bd_space +
MVNETA_MAX_TXD * sizeof(struct mvneta_tx_desc));
- buffer_loc.rx_buffers = (u32)
+ buffer_loc.rx_buffers = (phys_addr_t)
(bd_space +
MVNETA_MAX_TXD * sizeof(struct mvneta_tx_desc) +
MVNETA_MAX_RXD * sizeof(struct mvneta_rx_desc));
@@ -1608,7 +1639,10 @@ static int mvneta_probe(struct udevice *dev)
pp->base = (void __iomem *)pdata->iobase;
/* Configure MBUS address windows */
- mvneta_conf_mbus_windows(pp);
+ if (of_device_is_compatible(dev, "marvell,armada-3700-neta"))
+ mvneta_bypass_mbus_windows(pp);
+ else
+ mvneta_conf_mbus_windows(pp);
/* PHY interface is already decoded in mvneta_ofdata_to_platdata() */
pp->phy_interface = pdata->phy_interface;
@@ -1671,6 +1705,7 @@ static int mvneta_ofdata_to_platdata(struct udevice *dev)
static const struct udevice_id mvneta_ids[] = {
{ .compatible = "marvell,armada-370-neta" },
{ .compatible = "marvell,armada-xp-neta" },
+ { .compatible = "marvell,armada-3700-neta" },
{ }
};
diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig
new file mode 100644
index 0000000000..4240028403
--- /dev/null
+++ b/drivers/phy/marvell/Kconfig
@@ -0,0 +1,9 @@
+config MVEBU_COMPHY_SUPPORT
+ bool "ComPhy SerDes driver"
+ default n
+ help
+ Choose this option to add support
+ for Comphy driver.
+ This driver passes over the lanes
+ and initialize the lane depends on the
+ type and speed.
diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile
new file mode 100644
index 0000000000..f181505389
--- /dev/null
+++ b/drivers/phy/marvell/Makefile
@@ -0,0 +1,8 @@
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-$(CONFIG_MVEBU_COMPHY_SUPPORT) += comphy_core.o
+obj-$(CONFIG_MVEBU_COMPHY_SUPPORT) += comphy_mux.o
+obj-$(CONFIG_ARMADA_3700) += comphy_a3700.o
+obj-$(CONFIG_ARMADA_8K) += comphy_cp110.o
diff --git a/drivers/phy/marvell/comphy.h b/drivers/phy/marvell/comphy.h
new file mode 100644
index 0000000000..df5b7d507e
--- /dev/null
+++ b/drivers/phy/marvell/comphy.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _COMPHY_H_
+#define _COMPHY_H_
+
+#include <dt-bindings/comphy/comphy_data.h>
+#include <fdtdec.h>
+
+#if defined(DEBUG)
+#define debug_enter() printf("----> Enter %s\n", __func__);
+#define debug_exit() printf("<---- Exit %s\n", __func__);
+#else
+#define debug_enter()
+#define debug_exit()
+#endif
+
+/* COMPHY registers */
+#define COMMON_PHY_CFG1_REG 0x0
+#define COMMON_PHY_CFG1_PWR_UP_OFFSET 1
+#define COMMON_PHY_CFG1_PWR_UP_MASK \
+ (0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET)
+#define COMMON_PHY_CFG1_PIPE_SELECT_OFFSET 2
+#define COMMON_PHY_CFG1_PIPE_SELECT_MASK \
+ (0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET)
+#define COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET 13
+#define COMMON_PHY_CFG1_PWR_ON_RESET_MASK \
+ (0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET)
+#define COMMON_PHY_CFG1_CORE_RSTN_OFFSET 14
+#define COMMON_PHY_CFG1_CORE_RSTN_MASK \
+ (0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET)
+#define COMMON_PHY_PHY_MODE_OFFSET 15
+#define COMMON_PHY_PHY_MODE_MASK \
+ (0x1 << COMMON_PHY_PHY_MODE_OFFSET)
+
+#define COMMON_PHY_CFG6_REG 0x14
+#define COMMON_PHY_CFG6_IF_40_SEL_OFFSET 18
+#define COMMON_PHY_CFG6_IF_40_SEL_MASK \
+ (0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET)
+
+#define COMMON_SELECTOR_PHY_OFFSET 0x140
+#define COMMON_SELECTOR_PIPE_OFFSET 0x144
+
+#define COMMON_PHY_SD_CTRL1 0x148
+#define COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET 0
+#define COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK 0xFFFF
+#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET 24
+#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK \
+ (0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET)
+#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET 25
+#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK \
+ (0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET)
+#define COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET 26
+#define COMMON_PHY_SD_CTRL1_RXAUI1_MASK \
+ (0x1 << COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET)
+#define COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET 27
+#define COMMON_PHY_SD_CTRL1_RXAUI0_MASK \
+ (0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET)
+
+/* ToDo: Get this address via DT */
+#define MVEBU_CP0_REGS_BASE 0xF2000000UL
+
+#define DFX_DEV_GEN_CTRL12 (MVEBU_CP0_REGS_BASE + 0x400280)
+#define DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET 7
+#define DFX_DEV_GEN_PCIE_CLK_SRC_MASK \
+ (0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET)
+
+#define MAX_LANE_OPTIONS 10
+#define MAX_UTMI_PHY_COUNT 2
+
+struct comphy_mux_options {
+ u32 type;
+ u32 mux_value;
+};
+
+struct comphy_mux_data {
+ u32 max_lane_values;
+ struct comphy_mux_options mux_values[MAX_LANE_OPTIONS];
+};
+
+struct comphy_map {
+ u32 type;
+ u32 speed;
+ u32 invert;
+ bool clk_src;
+};
+
+struct chip_serdes_phy_config {
+ struct comphy_mux_data *mux_data;
+ int (*ptr_comphy_chip_init)(struct chip_serdes_phy_config *,
+ struct comphy_map *);
+ void __iomem *comphy_base_addr;
+ void __iomem *hpipe3_base_addr;
+ u32 comphy_lanes_count;
+ u32 comphy_mux_bitcount;
+ u32 comphy_index;
+};
+
+/* Register helper functions */
+void reg_set(void __iomem *addr, u32 data, u32 mask);
+void reg_set_silent(void __iomem *addr, u32 data, u32 mask);
+void reg_set16(void __iomem *addr, u16 data, u16 mask);
+void reg_set_silent16(void __iomem *addr, u16 data, u16 mask);
+
+/* SoC specific init functions */
+#ifdef CONFIG_ARMADA_3700
+int comphy_a3700_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *serdes_map);
+#else
+static inline int comphy_a3700_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *serdes_map)
+{
+ /*
+ * This function should never be called in this configuration, so
+ * lets return an error here.
+ */
+ return -1;
+}
+#endif
+
+#ifdef CONFIG_ARMADA_8K
+int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *serdes_map);
+#else
+static inline int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *serdes_map)
+{
+ /*
+ * This function should never be called in this configuration, so
+ * lets return an error here.
+ */
+ return -1;
+}
+#endif
+
+void comphy_dedicated_phys_init(void);
+
+/* MUX function */
+void comphy_mux_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *comphy_map_data,
+ void __iomem *selector_base);
+
+void comphy_pcie_config_set(u32 comphy_max_count,
+ struct comphy_map *serdes_map);
+void comphy_pcie_config_detect(u32 comphy_max_count,
+ struct comphy_map *serdes_map);
+void comphy_pcie_unit_general_config(u32 pex_index);
+
+#endif /* _COMPHY_H_ */
+
diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c
new file mode 100644
index 0000000000..faa62f90ae
--- /dev/null
+++ b/drivers/phy/marvell/comphy_a3700.c
@@ -0,0 +1,962 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "comphy_a3700.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct sgmii_phy_init_data_fix {
+ u16 addr;
+ u16 value;
+};
+
+/* Changes to 40M1G25 mode data required for running 40M3G125 init mode */
+static struct sgmii_phy_init_data_fix sgmii_phy_init_fix[] = {
+ {0x005, 0x07CC}, {0x015, 0x0000}, {0x01B, 0x0000}, {0x01D, 0x0000},
+ {0x01E, 0x0000}, {0x01F, 0x0000}, {0x020, 0x0000}, {0x021, 0x0030},
+ {0x026, 0x0888}, {0x04D, 0x0152}, {0x04F, 0xA020}, {0x050, 0x07CC},
+ {0x053, 0xE9CA}, {0x055, 0xBD97}, {0x071, 0x3015}, {0x076, 0x03AA},
+ {0x07C, 0x0FDF}, {0x0C2, 0x3030}, {0x0C3, 0x8000}, {0x0E2, 0x5550},
+ {0x0E3, 0x12A4}, {0x0E4, 0x7D00}, {0x0E6, 0x0C83}, {0x101, 0xFCC0},
+ {0x104, 0x0C10}
+};
+
+/* 40M1G25 mode init data */
+static u16 sgmii_phy_init[512] = {
+ /* 0 1 2 3 4 5 6 7 */
+ /*-----------------------------------------------------------*/
+ /* 8 9 A B C D E F */
+ 0x3110, 0xFD83, 0x6430, 0x412F, 0x82C0, 0x06FA, 0x4500, 0x6D26, /* 00 */
+ 0xAFC0, 0x8000, 0xC000, 0x0000, 0x2000, 0x49CC, 0x0BC9, 0x2A52, /* 08 */
+ 0x0BD2, 0x0CDE, 0x13D2, 0x0CE8, 0x1149, 0x10E0, 0x0000, 0x0000, /* 10 */
+ 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x4134, 0x0D2D, 0xFFFF, /* 18 */
+ 0xFFE0, 0x4030, 0x1016, 0x0030, 0x0000, 0x0800, 0x0866, 0x0000, /* 20 */
+ 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* 28 */
+ 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */
+ 0x0000, 0x0000, 0x000F, 0x6A62, 0x1988, 0x3100, 0x3100, 0x3100, /* 38 */
+ 0x3100, 0xA708, 0x2430, 0x0830, 0x1030, 0x4610, 0xFF00, 0xFF00, /* 40 */
+ 0x0060, 0x1000, 0x0400, 0x0040, 0x00F0, 0x0155, 0x1100, 0xA02A, /* 48 */
+ 0x06FA, 0x0080, 0xB008, 0xE3ED, 0x5002, 0xB592, 0x7A80, 0x0001, /* 50 */
+ 0x020A, 0x8820, 0x6014, 0x8054, 0xACAA, 0xFC88, 0x2A02, 0x45CF, /* 58 */
+ 0x000F, 0x1817, 0x2860, 0x064F, 0x0000, 0x0204, 0x1800, 0x6000, /* 60 */
+ 0x810F, 0x4F23, 0x4000, 0x4498, 0x0850, 0x0000, 0x000E, 0x1002, /* 68 */
+ 0x9D3A, 0x3009, 0xD066, 0x0491, 0x0001, 0x6AB0, 0x0399, 0x3780, /* 70 */
+ 0x0040, 0x5AC0, 0x4A80, 0x0000, 0x01DF, 0x0000, 0x0007, 0x0000, /* 78 */
+ 0x2D54, 0x00A1, 0x4000, 0x0100, 0xA20A, 0x0000, 0x0000, 0x0000, /* 80 */
+ 0x0000, 0x0000, 0x0000, 0x7400, 0x0E81, 0x1000, 0x1242, 0x0210, /* 88 */
+ 0x80DF, 0x0F1F, 0x2F3F, 0x4F5F, 0x6F7F, 0x0F1F, 0x2F3F, 0x4F5F, /* 90 */
+ 0x6F7F, 0x4BAD, 0x0000, 0x0000, 0x0800, 0x0000, 0x2400, 0xB651, /* 98 */
+ 0xC9E0, 0x4247, 0x0A24, 0x0000, 0xAF19, 0x1004, 0x0000, 0x0000, /* A0 */
+ 0x0000, 0x0013, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* A8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* B0 */
+ 0x0000, 0x0000, 0x0000, 0x0060, 0x0000, 0x0000, 0x0000, 0x0000, /* B8 */
+ 0x0000, 0x0000, 0x3010, 0xFA00, 0x0000, 0x0000, 0x0000, 0x0003, /* C0 */
+ 0x1618, 0x8200, 0x8000, 0x0400, 0x050F, 0x0000, 0x0000, 0x0000, /* C8 */
+ 0x4C93, 0x0000, 0x1000, 0x1120, 0x0010, 0x1242, 0x1242, 0x1E00, /* D0 */
+ 0x0000, 0x0000, 0x0000, 0x00F8, 0x0000, 0x0041, 0x0800, 0x0000, /* D8 */
+ 0x82A0, 0x572E, 0x2490, 0x14A9, 0x4E00, 0x0000, 0x0803, 0x0541, /* E0 */
+ 0x0C15, 0x0000, 0x0000, 0x0400, 0x2626, 0x0000, 0x0000, 0x4200, /* E8 */
+ 0x0000, 0xAA55, 0x1020, 0x0000, 0x0000, 0x5010, 0x0000, 0x0000, /* F0 */
+ 0x0000, 0x0000, 0x5000, 0x0000, 0x0000, 0x0000, 0x02F2, 0x0000, /* F8 */
+ 0x101F, 0xFDC0, 0x4000, 0x8010, 0x0110, 0x0006, 0x0000, 0x0000, /*100 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*108 */
+ 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04C6, 0x0000, /*110 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*118 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*120 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*128 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*130 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*138 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*140 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*148 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*150 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*158 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*160 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*168 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*170 */
+ 0x0000, 0x0000, 0x0000, 0x00F0, 0x08A2, 0x3112, 0x0A14, 0x0000, /*178 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*180 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*188 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*190 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*198 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1A0 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1A8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1B0 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1B8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1C0 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1C8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1D0 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1D8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1E0 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1E8 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1F0 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 /*1F8 */
+};
+
+/*
+ * comphy_poll_reg
+ *
+ * return: 1 on success, 0 on timeout
+ */
+static u32 comphy_poll_reg(void *addr, u32 val, u32 mask, u32 timeout,
+ u8 op_type)
+{
+ u32 rval = 0xDEAD;
+
+ for (; timeout > 0; timeout--) {
+ if (op_type == POLL_16B_REG)
+ rval = readw(addr); /* 16 bit */
+ else
+ rval = readl(addr) ; /* 32 bit */
+
+ if ((rval & mask) == val)
+ return 1;
+
+ udelay(10000);
+ }
+
+ debug("Time out waiting (%p = %#010x)\n", addr, rval);
+ return 0;
+}
+
+/*
+ * comphy_pcie_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_pcie_power_up(u32 speed, u32 invert)
+{
+ int ret;
+
+ debug_enter();
+
+ /*
+ * 1. Enable max PLL.
+ */
+ reg_set16((void __iomem *)LANE_CFG1_ADDR(PCIE),
+ bf_use_max_pll_rate, 0);
+
+ /*
+ * 2. Select 20 bit SERDES interface.
+ */
+ reg_set16((void __iomem *)GLOB_CLK_SRC_LO_ADDR(PCIE),
+ bf_cfg_sel_20b, 0);
+
+ /*
+ * 3. Force to use reg setting for PCIe mode
+ */
+ reg_set16((void __iomem *)MISC_REG1_ADDR(PCIE),
+ bf_sel_bits_pcie_force, 0);
+
+ /*
+ * 4. Change RX wait
+ */
+ reg_set16((void __iomem *)PWR_MGM_TIM1_ADDR(PCIE), 0x10C, 0xFFFF);
+
+ /*
+ * 5. Enable idle sync
+ */
+ reg_set16((void __iomem *)UNIT_CTRL_ADDR(PCIE),
+ 0x60 | rb_idle_sync_en, 0xFFFF);
+
+ /*
+ * 6. Enable the output of 100M/125M/500M clock
+ */
+ reg_set16((void __iomem *)MISC_REG0_ADDR(PCIE),
+ 0xA00D | rb_clk500m_en | rb_clk100m_125m_en, 0xFFFF);
+
+ /*
+ * 7. Enable TX
+ */
+ reg_set((void __iomem *)PHY_REF_CLK_ADDR, 0x1342, 0xFFFFFFFF);
+
+ /*
+ * 8. Check crystal jumper setting and program the Power and PLL
+ * Control accordingly
+ */
+ if (get_ref_clk() == 40) {
+ reg_set16((void __iomem *)PWR_PLL_CTRL_ADDR(PCIE),
+ 0xFC63, 0xFFFF); /* 40 MHz */
+ } else {
+ reg_set16((void __iomem *)PWR_PLL_CTRL_ADDR(PCIE),
+ 0xFC62, 0xFFFF); /* 25 MHz */
+ }
+
+ /*
+ * 9. Override Speed_PLL value and use MAC PLL
+ */
+ reg_set16((void __iomem *)KVCO_CAL_CTRL_ADDR(PCIE),
+ 0x0040 | rb_use_max_pll_rate, 0xFFFF);
+
+ /*
+ * 10. Check the Polarity invert bit
+ */
+ if (invert & PHY_POLARITY_TXD_INVERT) {
+ reg_set16((void __iomem *)SYNC_PATTERN_ADDR(PCIE),
+ phy_txd_inv, 0);
+ }
+
+ if (invert & PHY_POLARITY_RXD_INVERT) {
+ reg_set16((void __iomem *)SYNC_PATTERN_ADDR(PCIE),
+ phy_rxd_inv, 0);
+ }
+
+ /*
+ * 11. Release SW reset
+ */
+ reg_set16((void __iomem *)GLOB_PHY_CTRL0_ADDR(PCIE),
+ rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32,
+ bf_soft_rst | bf_mode_refdiv);
+
+ /* Wait for > 55 us to allow PCLK be enabled */
+ udelay(PLL_SET_DELAY_US);
+
+ /* Assert PCLK enabled */
+ ret = comphy_poll_reg((void *)LANE_STAT1_ADDR(PCIE), /* address */
+ rb_txdclk_pclk_en, /* value */
+ rb_txdclk_pclk_en, /* mask */
+ PLL_LOCK_TIMEOUT, /* timeout */
+ POLL_16B_REG); /* 16bit */
+ if (ret == 0)
+ printf("Failed to lock PCIe PLL\n");
+
+ debug_exit();
+
+ /* Return the status of the PLL */
+ return ret;
+}
+
+/*
+ * comphy_sata_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_sata_power_up(void)
+{
+ int ret;
+
+ debug_enter();
+
+ /*
+ * 0. Swap SATA TX lines
+ */
+ reg_set((void __iomem *)rh_vsreg_addr,
+ vphy_sync_pattern_reg, 0xFFFFFFFF);
+ reg_set((void __iomem *)rh_vsreg_data, bs_txd_inv, bs_txd_inv);
+
+ /*
+ * 1. Select 40-bit data width width
+ */
+ reg_set((void __iomem *)rh_vsreg_addr, vphy_loopback_reg0, 0xFFFFFFFF);
+ reg_set((void __iomem *)rh_vsreg_data, 0x800, bs_phyintf_40bit);
+
+ /*
+ * 2. Select reference clock and PHY mode (SATA)
+ */
+ reg_set((void __iomem *)rh_vsreg_addr, vphy_power_reg0, 0xFFFFFFFF);
+ if (get_ref_clk() == 40) {
+ reg_set((void __iomem *)rh_vsreg_data,
+ 0x3, 0x00FF); /* 40 MHz */
+ } else {
+ reg_set((void __iomem *)rh_vsreg_data,
+ 0x1, 0x00FF); /* 25 MHz */
+ }
+
+ /*
+ * 3. Use maximum PLL rate (no power save)
+ */
+ reg_set((void __iomem *)rh_vsreg_addr, vphy_calctl_reg, 0xFFFFFFFF);
+ reg_set((void __iomem *)rh_vsreg_data,
+ bs_max_pll_rate, bs_max_pll_rate);
+
+ /*
+ * 4. Reset reserved bit (??)
+ */
+ reg_set((void __iomem *)rh_vsreg_addr, vphy_reserve_reg, 0xFFFFFFFF);
+ reg_set((void __iomem *)rh_vsreg_data, 0, bs_phyctrl_frm_pin);
+
+ /*
+ * 5. Set vendor-specific configuration (??)
+ */
+ reg_set((void __iomem *)rh_vs0_a, vsata_ctrl_reg, 0xFFFFFFFF);
+ reg_set((void __iomem *)rh_vs0_d, bs_phy_pu_pll, bs_phy_pu_pll);
+
+ /* Wait for > 55 us to allow PLL be enabled */
+ udelay(PLL_SET_DELAY_US);
+
+ /* Assert SATA PLL enabled */
+ reg_set((void __iomem *)rh_vsreg_addr, vphy_loopback_reg0, 0xFFFFFFFF);
+ ret = comphy_poll_reg((void *)rh_vsreg_data, /* address */
+ bs_pll_ready_tx, /* value */
+ bs_pll_ready_tx, /* mask */
+ PLL_LOCK_TIMEOUT, /* timeout */
+ POLL_32B_REG); /* 32bit */
+ if (ret == 0)
+ printf("Failed to lock SATA PLL\n");
+
+ debug_exit();
+
+ return ret;
+}
+
+/*
+ * comphy_usb3_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert)
+{
+ int ret;
+
+ debug_enter();
+
+ /*
+ * 1. Power up OTG module
+ */
+ reg_set((void __iomem *)USB2_PHY_OTG_CTRL_ADDR, rb_pu_otg, 0);
+
+ /*
+ * 2. Set counter for 100us pulse in USB3 Host and Device
+ * restore default burst size limit (Reference Clock 31:24)
+ */
+ reg_set((void __iomem *)USB3_CTRPUL_VAL_REG,
+ 0x8 << 24, rb_usb3_ctr_100ns);
+
+
+ /* 0xd005c300 = 0x1001 */
+ /* set PRD_TXDEEMPH (3.5db de-emph) */
+ reg_set16((void __iomem *)LANE_CFG0_ADDR(USB3), 0x1, 0xFF);
+
+ /*
+ * unset BIT0: set Tx Electrical Idle Mode: Transmitter is in
+ * low impedance mode during electrical idle
+ */
+ /* unset BIT4: set G2 Tx Datapath with no Delayed Latency */
+ /* unset BIT6: set Tx Detect Rx Mode at LoZ mode */
+ reg_set16((void __iomem *)LANE_CFG1_ADDR(USB3), 0x0, 0xFFFF);
+
+
+ /* 0xd005c310 = 0x93: set Spread Spectrum Clock Enabled */
+ reg_set16((void __iomem *)LANE_CFG4_ADDR(USB3),
+ bf_spread_spectrum_clock_en, 0x80);
+
+ /*
+ * set Override Margining Controls From the MAC: Use margining signals
+ * from lane configuration
+ */
+ reg_set16((void __iomem *)TEST_MODE_CTRL_ADDR(USB3),
+ rb_mode_margin_override, 0xFFFF);
+
+ /* set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles */
+ /* set Mode Clock Source = PCLK is generated from REFCLK */
+ reg_set16((void __iomem *)GLOB_CLK_SRC_LO_ADDR(USB3), 0x0, 0xFF);
+
+ /* set G2 Spread Spectrum Clock Amplitude at 4K */
+ reg_set16((void __iomem *)GEN2_SETTING_2_ADDR(USB3), g2_tx_ssc_amp,
+ 0xF000);
+
+ /*
+ * unset G3 Spread Spectrum Clock Amplitude & set G3 TX and RX Register
+ * Master Current Select
+ */
+ reg_set16((void __iomem *)GEN2_SETTING_3_ADDR(USB3), 0x0, 0xFFFF);
+
+ /*
+ * 3. Check crystal jumper setting and program the Power and PLL
+ * Control accordingly
+ */
+ if (get_ref_clk() == 40) {
+ reg_set16((void __iomem *)PWR_PLL_CTRL_ADDR(USB3), 0xFCA3,
+ 0xFFFF); /* 40 MHz */
+ } else {
+ reg_set16((void __iomem *)PWR_PLL_CTRL_ADDR(USB3), 0xFCA2,
+ 0xFFFF); /* 25 MHz */
+ }
+
+ /*
+ * 4. Change RX wait
+ */
+ reg_set16((void __iomem *)PWR_MGM_TIM1_ADDR(USB3), 0x10C, 0xFFFF);
+
+ /*
+ * 5. Enable idle sync
+ */
+ reg_set16((void __iomem *)UNIT_CTRL_ADDR(USB3), 0x60 | rb_idle_sync_en,
+ 0xFFFF);
+
+ /*
+ * 6. Enable the output of 500M clock
+ */
+ reg_set16((void __iomem *)MISC_REG0_ADDR(USB3), 0xA00D | rb_clk500m_en,
+ 0xFFFF);
+
+ /*
+ * 7. Set 20-bit data width
+ */
+ reg_set16((void __iomem *)DIG_LB_EN_ADDR(USB3), 0x0400, 0xFFFF);
+
+ /*
+ * 8. Override Speed_PLL value and use MAC PLL
+ */
+ reg_set16((void __iomem *)KVCO_CAL_CTRL_ADDR(USB3),
+ 0x0040 | rb_use_max_pll_rate, 0xFFFF);
+
+ /*
+ * 9. Check the Polarity invert bit
+ */
+ if (invert & PHY_POLARITY_TXD_INVERT) {
+ reg_set16((void __iomem *)SYNC_PATTERN_ADDR(USB3),
+ phy_txd_inv, 0);
+ }
+
+ if (invert & PHY_POLARITY_RXD_INVERT) {
+ reg_set16((void __iomem *)SYNC_PATTERN_ADDR(USB3),
+ phy_rxd_inv, 0);
+ }
+
+ /*
+ * 10. Release SW reset
+ */
+ reg_set16((void __iomem *)GLOB_PHY_CTRL0_ADDR(USB3),
+ rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32 | 0x20,
+ 0xFFFF);
+
+ /* Wait for > 55 us to allow PCLK be enabled */
+ udelay(PLL_SET_DELAY_US);
+
+ /* Assert PCLK enabled */
+ ret = comphy_poll_reg((void *)LANE_STAT1_ADDR(USB3), /* address */
+ rb_txdclk_pclk_en, /* value */
+ rb_txdclk_pclk_en, /* mask */
+ PLL_LOCK_TIMEOUT, /* timeout */
+ POLL_16B_REG); /* 16bit */
+ if (ret == 0)
+ printf("Failed to lock USB3 PLL\n");
+
+ /*
+ * Set Soft ID for Host mode (Device mode works with Hard ID
+ * detection)
+ */
+ if (type == PHY_TYPE_USB3_HOST0) {
+ /*
+ * set BIT0: set ID_MODE of Host/Device = "Soft ID" (BIT1)
+ * clear BIT1: set SOFT_ID = Host
+ * set BIT4: set INT_MODE = ID. Interrupt Mode: enable
+ * interrupt by ID instead of using both interrupts
+ * of HOST and Device ORed simultaneously
+ * INT_MODE=ID in order to avoid unexpected
+ * behaviour or both interrupts together
+ */
+ reg_set((void __iomem *)USB32_CTRL_BASE,
+ usb32_ctrl_id_mode | usb32_ctrl_int_mode,
+ usb32_ctrl_id_mode | usb32_ctrl_soft_id |
+ usb32_ctrl_int_mode);
+ }
+
+ debug_exit();
+
+ return ret;
+}
+
+/*
+ * comphy_usb2_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_usb2_power_up(u8 usb32)
+{
+ int ret;
+
+ debug_enter();
+
+ if (usb32 != 0 && usb32 != 1) {
+ printf("invalid usb32 value: (%d), should be either 0 or 1\n",
+ usb32);
+ debug_exit();
+ return 0;
+ }
+
+ /*
+ * 0. Setup PLL. 40MHz clock uses defaults.
+ * See "PLL Settings for Typical REFCLK" table
+ */
+ if (get_ref_clk() == 25) {
+ reg_set((void __iomem *)USB2_PHY_BASE(usb32),
+ 5 | (96 << 16), 0x3F | (0xFF << 16) | (0x3 << 28));
+ }
+
+ /*
+ * 1. PHY pull up and disable USB2 suspend
+ */
+ reg_set((void __iomem *)USB2_PHY_CTRL_ADDR(usb32),
+ RB_USB2PHY_SUSPM(usb32) | RB_USB2PHY_PU(usb32), 0);
+
+ if (usb32 != 0) {
+ /*
+ * 2. Power up OTG module
+ */
+ reg_set((void __iomem *)USB2_PHY_OTG_CTRL_ADDR, rb_pu_otg, 0);
+
+ /*
+ * 3. Configure PHY charger detection
+ */
+ reg_set((void __iomem *)USB2_PHY_CHRGR_DET_ADDR, 0,
+ rb_cdp_en | rb_dcp_en | rb_pd_en | rb_cdp_dm_auto |
+ rb_enswitch_dp | rb_enswitch_dm | rb_pu_chrg_dtc);
+ }
+
+ /* Assert PLL calibration done */
+ ret = comphy_poll_reg((void *)USB2_PHY_CAL_CTRL_ADDR(usb32),
+ rb_usb2phy_pllcal_done, /* value */
+ rb_usb2phy_pllcal_done, /* mask */
+ PLL_LOCK_TIMEOUT, /* timeout */
+ POLL_32B_REG); /* 32bit */
+ if (ret == 0)
+ printf("Failed to end USB2 PLL calibration\n");
+
+ /* Assert impedance calibration done */
+ ret = comphy_poll_reg((void *)USB2_PHY_CAL_CTRL_ADDR(usb32),
+ rb_usb2phy_impcal_done, /* value */
+ rb_usb2phy_impcal_done, /* mask */
+ PLL_LOCK_TIMEOUT, /* timeout */
+ POLL_32B_REG); /* 32bit */
+ if (ret == 0)
+ printf("Failed to end USB2 impedance calibration\n");
+
+ /* Assert squetch calibration done */
+ ret = comphy_poll_reg((void *)USB2_PHY_RX_CHAN_CTRL1_ADDR(usb32),
+ rb_usb2phy_sqcal_done, /* value */
+ rb_usb2phy_sqcal_done, /* mask */
+ PLL_LOCK_TIMEOUT, /* timeout */
+ POLL_32B_REG); /* 32bit */
+ if (ret == 0)
+ printf("Failed to end USB2 unknown calibration\n");
+
+ /* Assert PLL is ready */
+ ret = comphy_poll_reg((void *)USB2_PHY_PLL_CTRL0_ADDR(usb32),
+ rb_usb2phy_pll_ready, /* value */
+ rb_usb2phy_pll_ready, /* mask */
+ PLL_LOCK_TIMEOUT, /* timeout */
+ POLL_32B_REG); /* 32bit */
+
+ if (ret == 0)
+ printf("Failed to lock USB2 PLL\n");
+
+ debug_exit();
+
+ return ret;
+}
+
+/*
+ * comphy_emmc_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_emmc_power_up(void)
+{
+ debug_enter();
+
+ /*
+ * 1. Bus power ON, Bus voltage 1.8V
+ */
+ reg_set((void __iomem *)SDIO_HOST_CTRL1_ADDR, 0xB00, 0xF00);
+
+ /*
+ * 2. Set FIFO parameters
+ */
+ reg_set((void __iomem *)SDIO_SDHC_FIFO_ADDR, 0x315, 0xFFFFFFFF);
+
+ /*
+ * 3. Set Capabilities 1_2
+ */
+ reg_set((void __iomem *)SDIO_CAP_12_ADDR, 0x25FAC8B2, 0xFFFFFFFF);
+
+ /*
+ * 4. Set Endian
+ */
+ reg_set((void __iomem *)SDIO_ENDIAN_ADDR, 0x00c00000, 0);
+
+ /*
+ * 4. Init PHY
+ */
+ reg_set((void __iomem *)SDIO_PHY_TIMING_ADDR, 0x80000000, 0x80000000);
+ reg_set((void __iomem *)SDIO_PHY_PAD_CTRL0_ADDR, 0x50000000,
+ 0xF0000000);
+
+ /*
+ * 5. DLL reset
+ */
+ reg_set((void __iomem *)SDIO_DLL_RST_ADDR, 0xFFFEFFFF, 0);
+ reg_set((void __iomem *)SDIO_DLL_RST_ADDR, 0x00010000, 0);
+
+ debug_exit();
+
+ return 1;
+}
+
+/*
+ * comphy_sgmii_power_up
+ *
+ * return:
+ */
+static void comphy_sgmii_phy_init(u32 lane, u32 speed)
+{
+ const int fix_arr_sz = ARRAY_SIZE(sgmii_phy_init_fix);
+ int addr, fix_idx;
+ u16 val;
+
+ fix_idx = 0;
+ for (addr = 0; addr < 512; addr++) {
+ /*
+ * All PHY register values are defined in full for 3.125Gbps
+ * SERDES speed. The values required for 1.25 Gbps are almost
+ * the same and only few registers should be "fixed" in
+ * comparison to 3.125 Gbps values. These register values are
+ * stored in "sgmii_phy_init_fix" array.
+ */
+ if ((speed != PHY_SPEED_1_25G) &&
+ (sgmii_phy_init_fix[fix_idx].addr == addr)) {
+ /* Use new value */
+ val = sgmii_phy_init_fix[fix_idx].value;
+ if (fix_idx < fix_arr_sz)
+ fix_idx++;
+ } else {
+ val = sgmii_phy_init[addr];
+ }
+
+ phy_write16(lane, addr, val, 0xFFFF);
+ }
+}
+
+/*
+ * comphy_sgmii_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert)
+{
+ int ret;
+
+ debug_enter();
+
+ /*
+ * 1. Configure PHY to SATA/SAS mode by setting pin PIN_PIPE_SEL=0
+ */
+ reg_set((void __iomem *)COMPHY_SEL_ADDR, 0, rf_compy_select(lane));
+
+ /*
+ * 2. Reset PHY by setting PHY input port PIN_RESET=1.
+ * 3. Set PHY input port PIN_TX_IDLE=1, PIN_PU_IVREF=1 to keep
+ * PHY TXP/TXN output to idle state during PHY initialization
+ * 4. Set PHY input port PIN_PU_PLL=0, PIN_PU_RX=0, PIN_PU_TX=0.
+ */
+ reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane),
+ rb_pin_reset_comphy | rb_pin_tx_idle | rb_pin_pu_iveref,
+ rb_pin_reset_core | rb_pin_pu_pll |
+ rb_pin_pu_rx | rb_pin_pu_tx);
+
+ /*
+ * 5. Release reset to the PHY by setting PIN_RESET=0.
+ */
+ reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane),
+ 0, rb_pin_reset_comphy);
+
+ /*
+ * 7. Set PIN_PHY_GEN_TX[3:0] and PIN_PHY_GEN_RX[3:0] to decide
+ * COMPHY bit rate
+ */
+ if (speed == PHY_SPEED_3_125G) { /* 3.125 GHz */
+ reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane),
+ (0x8 << rf_gen_rx_sel_shift) |
+ (0x8 << rf_gen_tx_sel_shift),
+ rf_gen_rx_select | rf_gen_tx_select);
+
+ } else if (speed == PHY_SPEED_1_25G) { /* 1.25 GHz */
+ reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane),
+ (0x6 << rf_gen_rx_sel_shift) |
+ (0x6 << rf_gen_tx_sel_shift),
+ rf_gen_rx_select | rf_gen_tx_select);
+ } else {
+ printf("Unsupported COMPHY speed!\n");
+ return 0;
+ }
+
+ /*
+ * 8. Wait 1mS for bandgap and reference clocks to stabilize;
+ * then start SW programming.
+ */
+ mdelay(10);
+
+ /* 9. Program COMPHY register PHY_MODE */
+ phy_write16(lane, PHY_PWR_PLL_CTRL_ADDR,
+ PHY_MODE_SGMII << rf_phy_mode_shift, rf_phy_mode_mask);
+
+ /*
+ * 10. Set COMPHY register REFCLK_SEL to select the correct REFCLK
+ * source
+ */
+ phy_write16(lane, PHY_MISC_REG0_ADDR, 0, rb_ref_clk_sel);
+
+ /*
+ * 11. Set correct reference clock frequency in COMPHY register
+ * REF_FREF_SEL.
+ */
+ if (get_ref_clk() == 40) {
+ phy_write16(lane, PHY_PWR_PLL_CTRL_ADDR,
+ 0x4 << rf_ref_freq_sel_shift, rf_ref_freq_sel_mask);
+ } else {
+ /* 25MHz */
+ phy_write16(lane, PHY_PWR_PLL_CTRL_ADDR,
+ 0x1 << rf_ref_freq_sel_shift, rf_ref_freq_sel_mask);
+ }
+
+ /* 12. Program COMPHY register PHY_GEN_MAX[1:0] */
+ /*
+ * This step is mentioned in the flow received from verification team.
+ * However the PHY_GEN_MAX value is only meaningful for other
+ * interfaces (not SGMII). For instance, it selects SATA speed
+ * 1.5/3/6 Gbps or PCIe speed 2.5/5 Gbps
+ */
+
+ /*
+ * 13. Program COMPHY register SEL_BITS to set correct parallel data
+ * bus width
+ */
+ /* 10bit */
+ phy_write16(lane, PHY_DIG_LB_EN_ADDR, 0, rf_data_width_mask);
+
+ /*
+ * 14. As long as DFE function needs to be enabled in any mode,
+ * COMPHY register DFE_UPDATE_EN[5:0] shall be programmed to 0x3F
+ * for real chip during COMPHY power on.
+ */
+ /*
+ * The step 14 exists (and empty) in the original initialization flow
+ * obtained from the verification team. According to the functional
+ * specification DFE_UPDATE_EN already has the default value 0x3F
+ */
+
+ /*
+ * 15. Program COMPHY GEN registers.
+ * These registers should be programmed based on the lab testing
+ * result to achieve optimal performance. Please contact the CEA
+ * group to get the related GEN table during real chip bring-up.
+ * We only requred to run though the entire registers programming
+ * flow defined by "comphy_sgmii_phy_init" when the REF clock is
+ * 40 MHz. For REF clock 25 MHz the default values stored in PHY
+ * registers are OK.
+ */
+ debug("Running C-DPI phy init %s mode\n",
+ speed == PHY_SPEED_3_125G ? "2G5" : "1G");
+ if (get_ref_clk() == 40)
+ comphy_sgmii_phy_init(lane, speed);
+
+ /*
+ * 16. [Simulation Only] should not be used for real chip.
+ * By pass power up calibration by programming EXT_FORCE_CAL_DONE
+ * (R02h[9]) to 1 to shorten COMPHY simulation time.
+ */
+ /*
+ * 17. [Simulation Only: should not be used for real chip]
+ * Program COMPHY register FAST_DFE_TIMER_EN=1 to shorten RX
+ * training simulation time.
+ */
+
+ /*
+ * 18. Check the PHY Polarity invert bit
+ */
+ if (invert & PHY_POLARITY_TXD_INVERT)
+ phy_write16(lane, PHY_SYNC_PATTERN_ADDR, phy_txd_inv, 0);
+
+ if (invert & PHY_POLARITY_RXD_INVERT)
+ phy_write16(lane, PHY_SYNC_PATTERN_ADDR, phy_rxd_inv, 0);
+
+ /*
+ * 19. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1
+ * to start PHY power up sequence. All the PHY register
+ * programming should be done before PIN_PU_PLL=1. There should be
+ * no register programming for normal PHY operation from this point.
+ */
+ reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane),
+ rb_pin_pu_pll | rb_pin_pu_rx | rb_pin_pu_tx,
+ rb_pin_pu_pll | rb_pin_pu_rx | rb_pin_pu_tx);
+
+ /*
+ * 20. Wait for PHY power up sequence to finish by checking output ports
+ * PIN_PLL_READY_TX=1 and PIN_PLL_READY_RX=1.
+ */
+ ret = comphy_poll_reg((void *)COMPHY_PHY_STAT1_ADDR(lane), /* address */
+ rb_pll_ready_tx | rb_pll_ready_rx, /* value */
+ rb_pll_ready_tx | rb_pll_ready_rx, /* mask */
+ PLL_LOCK_TIMEOUT, /* timeout */
+ POLL_32B_REG); /* 32bit */
+ if (ret == 0)
+ printf("Failed to lock PLL for SGMII PHY %d\n", lane);
+
+ /*
+ * 21. Set COMPHY input port PIN_TX_IDLE=0
+ */
+ reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane),
+ 0x0, rb_pin_tx_idle);
+
+ /*
+ * 22. After valid data appear on PIN_RXDATA bus, set PIN_RX_INIT=1.
+ * to start RX initialization. PIN_RX_INIT_DONE will be cleared to
+ * 0 by the PHY. After RX initialization is done, PIN_RX_INIT_DONE
+ * will be set to 1 by COMPHY. Set PIN_RX_INIT=0 after
+ * PIN_RX_INIT_DONE= 1.
+ * Please refer to RX initialization part for details.
+ */
+ reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane), rb_phy_rx_init,
+ 0x0);
+
+ ret = comphy_poll_reg((void *)COMPHY_PHY_STAT1_ADDR(lane), /* address */
+ rb_rx_init_done, /* value */
+ rb_rx_init_done, /* mask */
+ PLL_LOCK_TIMEOUT, /* timeout */
+ POLL_32B_REG); /* 32bit */
+ if (ret == 0)
+ printf("Failed to init RX of SGMII PHY %d\n", lane);
+
+ debug_exit();
+
+ return ret;
+}
+
+void comphy_dedicated_phys_init(void)
+{
+ int node, usb32, ret = 1;
+ const void *blob = gd->fdt_blob;
+
+ debug_enter();
+
+ for (usb32 = 0; usb32 <= 1; usb32++) {
+ /*
+ * There are 2 UTMI PHYs in this SOC.
+ * One is independendent and one is paired with USB3 port (OTG)
+ */
+ if (usb32 == 0) {
+ node = fdt_node_offset_by_compatible(
+ blob, -1, "marvell,armada-3700-ehci");
+ } else {
+ node = fdt_node_offset_by_compatible(
+ blob, -1, "marvell,armada3700-xhci");
+ }
+
+ if (node > 0) {
+ if (fdtdec_get_is_enabled(blob, node)) {
+ ret = comphy_usb2_power_up(usb32);
+ if (ret == 0)
+ printf("Failed to initialize UTMI PHY\n");
+ else
+ debug("UTMI PHY init succeed\n");
+ } else {
+ debug("USB%d node is disabled\n",
+ usb32 == 0 ? 2 : 3);
+ }
+ } else {
+ debug("No USB%d node in DT\n", usb32 == 0 ? 2 : 3);
+ }
+ }
+
+ node = fdt_node_offset_by_compatible(blob, -1,
+ "marvell,armada-3700-ahci");
+ if (node > 0) {
+ if (fdtdec_get_is_enabled(blob, node)) {
+ ret = comphy_sata_power_up();
+ if (ret == 0)
+ printf("Failed to initialize SATA PHY\n");
+ else
+ debug("SATA PHY init succeed\n");
+ } else {
+ debug("SATA node is disabled\n");
+ }
+ } else {
+ debug("No SATA node in DT\n");
+ }
+
+ node = fdt_node_offset_by_compatible(blob, -1,
+ "marvell,armada-3700-sdio");
+ if (node <= 0) {
+ debug("No SDIO node in DT, looking for MMC one\n");
+ node = fdt_node_offset_by_compatible(blob, -1,
+ "marvell,xenon-sdhci");
+ }
+
+ if (node > 0) {
+ if (fdtdec_get_is_enabled(blob, node)) {
+ ret = comphy_emmc_power_up();
+ if (ret == 0)
+ printf("Failed to initialize SDIO/eMMC PHY\n");
+ else
+ debug("SDIO/eMMC PHY init succeed\n");
+ } else {
+ debug("SDIO/eMMC node is disabled\n");
+ }
+ } else {
+ debug("No SDIO/eMMC node in DT\n");
+ }
+
+ debug_exit();
+}
+
+int comphy_a3700_init(struct chip_serdes_phy_config *chip_cfg,
+ struct comphy_map *serdes_map)
+{
+ struct comphy_map *comphy_map;
+ u32 comphy_max_count = chip_cfg->comphy_lanes_count;
+ u32 lane, ret = 0;
+
+ debug_enter();
+
+ for (lane = 0, comphy_map = serdes_map; lane < comphy_max_count;
+ lane++, comphy_map++) {
+ debug("Initialize serdes number %d\n", lane);
+ debug("Serdes type = 0x%x invert=%d\n",
+ comphy_map->type, comphy_map->invert);
+
+ switch (comphy_map->type) {
+ case PHY_TYPE_UNCONNECTED:
+ continue;
+ break;
+
+ case PHY_TYPE_PEX0:
+ ret = comphy_pcie_power_up(comphy_map->speed,
+ comphy_map->invert);
+ break;
+
+ case PHY_TYPE_USB3_HOST0:
+ case PHY_TYPE_USB3_DEVICE:
+ ret = comphy_usb3_power_up(comphy_map->type,
+ comphy_map->speed,
+ comphy_map->invert);
+ break;
+
+ case PHY_TYPE_SGMII0:
+ case PHY_TYPE_SGMII1:
+ ret = comphy_sgmii_power_up(lane, comphy_map->speed,
+ comphy_map->invert);
+ break;
+
+ default:
+ debug("Unknown SerDes type, skip initialize SerDes %d\n",
+ lane);
+ ret = 1;
+ break;
+ }
+ if (ret == 0)
+ printf("PLL is not locked - Failed to initialize lane %d\n",
+ lane);
+ }
+
+ debug_exit();
+ return ret;
+}
diff --git a/drivers/phy/marvell/comphy_a3700.h b/drivers/phy/marvell/comphy_a3700.h
new file mode 100644
index 0000000000..eb2ed7b317
--- /dev/null
+++ b/drivers/phy/marvell/comphy_a3700.h
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _COMPHY_A3700_H_
+#define _COMPHY_A3700_H_
+
+#include "comphy.h"
+#include "comphy_hpipe.h"
+
+#define MVEBU_REG(offs) ((uintptr_t)MVEBU_REGISTER(offs))
+
+#define DEFAULT_REFCLK_MHZ 25
+#define PLL_SET_DELAY_US 600
+#define PLL_LOCK_TIMEOUT 1000
+#define POLL_16B_REG 1
+#define POLL_32B_REG 0
+
+/*
+ * COMPHY SB definitions
+ */
+#define COMPHY_SEL_ADDR MVEBU_REG(0x0183FC)
+#define rf_compy_select(lane) (0x1 << (((lane) == 1) ? 4 : 0))
+
+#define COMPHY_PHY_CFG1_ADDR(lane) MVEBU_REG(0x018300 + (lane) * 0x28)
+#define rb_pin_pu_iveref BIT(1)
+#define rb_pin_reset_core BIT(11)
+#define rb_pin_reset_comphy BIT(12)
+#define rb_pin_pu_pll BIT(16)
+#define rb_pin_pu_rx BIT(17)
+#define rb_pin_pu_tx BIT(18)
+#define rb_pin_tx_idle BIT(19)
+#define rf_gen_rx_sel_shift 22
+#define rf_gen_rx_select (0xFF << rf_gen_rx_sel_shift)
+#define rf_gen_tx_sel_shift 26
+#define rf_gen_tx_select (0xFF << rf_gen_tx_sel_shift)
+#define rb_phy_rx_init BIT(30)
+
+#define COMPHY_PHY_STAT1_ADDR(lane) MVEBU_REG(0x018318 + (lane) * 0x28)
+#define rb_rx_init_done BIT(0)
+#define rb_pll_ready_rx BIT(2)
+#define rb_pll_ready_tx BIT(3)
+
+/*
+ * PCIe/USB/SGMII definitions
+ */
+#define PCIE_BASE MVEBU_REG(0x070000)
+#define PCIETOP_BASE MVEBU_REG(0x080000)
+#define PCIE_RAMBASE MVEBU_REG(0x08C000)
+#define PCIEPHY_BASE MVEBU_REG(0x01F000)
+#define PCIEPHY_SHFT 2
+
+#define USB32_BASE MVEBU_REG(0x050000) /* usb3 device */
+#define USB32H_BASE MVEBU_REG(0x058000) /* usb3 host */
+#define USB3PHY_BASE MVEBU_REG(0x05C000)
+#define USB2PHY_BASE MVEBU_REG(0x05D000)
+#define USB2PHY2_BASE MVEBU_REG(0x05F000)
+#define USB32_CTRL_BASE MVEBU_REG(0x05D800)
+#define USB3PHY_SHFT 2
+
+#define SGMIIPHY_BASE(l) (l == 1 ? USB3PHY_BASE : PCIEPHY_BASE)
+#define SGMIIPHY_ADDR(l, a) (((a & 0x00007FF) * 2) | SGMIIPHY_BASE(l))
+
+#define phy_read16(l, a) read16((void __iomem *)SGMIIPHY_ADDR(l, a))
+#define phy_write16(l, a, data, mask) \
+ reg_set16((void __iomem *)SGMIIPHY_ADDR(l, a), data, mask)
+
+/* units */
+#define PCIE 1
+#define USB3 2
+
+#define PHY_BASE(unit) ((unit == PCIE) ? PCIEPHY_BASE : USB3PHY_BASE)
+#define PHY_SHFT(unit) ((unit == PCIE) ? PCIEPHY_SHFT : USB3PHY_SHFT)
+
+/* bit definition for USB32_CTRL_BASE (USB32 Control Mode) */
+#define usb32_ctrl_id_mode BIT(0)
+#define usb32_ctrl_soft_id BIT(1)
+#define usb32_ctrl_int_mode BIT(4)
+
+
+#define PHY_PWR_PLL_CTRL_ADDR 0x01 /* for phy_read16 and phy_write16 */
+#define PWR_PLL_CTRL_ADDR(unit) \
+ (PHY_PWR_PLL_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rf_phy_mode_shift 5
+#define rf_phy_mode_mask (0x7 << rf_phy_mode_shift)
+#define rf_ref_freq_sel_shift 0
+#define rf_ref_freq_sel_mask (0x1F << rf_ref_freq_sel_shift)
+#define PHY_MODE_SGMII 0x4
+
+/* for phy_read16 and phy_write16 */
+#define PHY_REG_KVCO_CAL_CTRL_ADDR 0x02
+#define KVCO_CAL_CTRL_ADDR(unit) \
+ (PHY_REG_KVCO_CAL_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rb_use_max_pll_rate BIT(12)
+#define rb_force_calibration_done BIT(9)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_DIG_LB_EN_ADDR 0x23
+#define DIG_LB_EN_ADDR(unit) \
+ (PHY_DIG_LB_EN_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rf_data_width_shift 10
+#define rf_data_width_mask (0x3 << rf_data_width_shift)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_SYNC_PATTERN_ADDR 0x24
+#define SYNC_PATTERN_ADDR(unit) \
+ (PHY_SYNC_PATTERN_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define phy_txd_inv BIT(10)
+#define phy_rxd_inv BIT(11)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_REG_UNIT_CTRL_ADDR 0x48
+#define UNIT_CTRL_ADDR(unit) \
+ (PHY_REG_UNIT_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rb_idle_sync_en BIT(12)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_REG_GEN2_SETTINGS_2 0x3e
+#define GEN2_SETTING_2_ADDR(unit) \
+ (PHY_REG_GEN2_SETTINGS_2 * PHY_SHFT(unit) + PHY_BASE(unit))
+#define g2_tx_ssc_amp BIT(14)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_REG_GEN2_SETTINGS_3 0x3f
+#define GEN2_SETTING_3_ADDR(unit) \
+ (PHY_REG_GEN2_SETTINGS_3 * PHY_SHFT(unit) + PHY_BASE(unit))
+
+/* for phy_read16 and phy_write16 */
+#define PHY_MISC_REG0_ADDR 0x4f
+#define MISC_REG0_ADDR(unit) \
+ (PHY_MISC_REG0_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rb_clk100m_125m_en BIT(4)
+#define rb_clk500m_en BIT(7)
+#define rb_ref_clk_sel BIT(10)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_REG_IFACE_REF_CLK_CTRL_ADDR 0x51
+#define UNIT_IFACE_REF_CLK_CTRL_ADDR(unit) \
+ (PHY_REG_IFACE_REF_CLK_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rb_ref1m_gen_div_force BIT(8)
+#define rf_ref1m_gen_div_value_shift 0
+#define rf_ref1m_gen_div_value_mask (0xFF << rf_ref1m_gen_div_value_shift)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_REG_ERR_CNT_CONST_CTRL_ADDR 0x6A
+#define UNIT_ERR_CNT_CONST_CTRL_ADDR(unit) \
+ (PHY_REG_ERR_CNT_CONST_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rb_fast_dfe_enable BIT(13)
+
+#define MISC_REG1_ADDR(u) (0x73 * PHY_SHFT(u) + PHY_BASE(u))
+#define bf_sel_bits_pcie_force BIT(15)
+
+#define LANE_CFG0_ADDR(u) (0x180 * PHY_SHFT(u) + PHY_BASE(u))
+#define bf_use_max_pll_rate BIT(9)
+#define LANE_CFG1_ADDR(u) (0x181 * PHY_SHFT(u) + PHY_BASE(u))
+#define bf_use_max_pll_rate BIT(9)
+/* 0x5c310 = 0x93 (set BIT7) */
+#define LANE_CFG4_ADDR(u) (0x188 * PHY_SHFT(u) + PHY_BASE(u))
+#define bf_spread_spectrum_clock_en BIT(7)
+
+#define LANE_STAT1_ADDR(u) (0x183 * PHY_SHFT(u) + PHY_BASE(u))
+#define rb_txdclk_pclk_en BIT(0)
+
+#define GLOB_PHY_CTRL0_ADDR(u) (0x1c1 * PHY_SHFT(u) + PHY_BASE(u))
+#define bf_soft_rst BIT(0)
+#define bf_mode_refdiv 0x30
+#define rb_mode_core_clk_freq_sel BIT(9)
+#define rb_mode_pipe_width_32 BIT(3)
+
+#define TEST_MODE_CTRL_ADDR(u) (0x1c2 * PHY_SHFT(u) + PHY_BASE(u))
+#define rb_mode_margin_override BIT(2)
+
+#define GLOB_CLK_SRC_LO_ADDR(u) (0x1c3 * PHY_SHFT(u) + PHY_BASE(u))
+#define bf_cfg_sel_20b BIT(15)
+
+#define PWR_MGM_TIM1_ADDR(u) (0x1d0 * PHY_SHFT(u) + PHY_BASE(u))
+
+#define PHY_REF_CLK_ADDR (0x4814 + PCIE_BASE)
+
+#define USB3_CTRPUL_VAL_REG (0x20 + USB32_BASE)
+#define USB3H_CTRPUL_VAL_REG (0x3454 + USB32H_BASE)
+#define rb_usb3_ctr_100ns 0xff000000
+
+#define USB2_OTG_PHY_CTRL_ADDR (0x820 + USB2PHY_BASE)
+#define rb_usb2phy_suspm BIT(14)
+#define rb_usb2phy_pu BIT(0)
+
+#define USB2_PHY_OTG_CTRL_ADDR (0x34 + USB2PHY_BASE)
+#define rb_pu_otg BIT(4)
+
+#define USB2_PHY_CHRGR_DET_ADDR (0x38 + USB2PHY_BASE)
+#define rb_cdp_en BIT(2)
+#define rb_dcp_en BIT(3)
+#define rb_pd_en BIT(4)
+#define rb_pu_chrg_dtc BIT(5)
+#define rb_cdp_dm_auto BIT(7)
+#define rb_enswitch_dp BIT(12)
+#define rb_enswitch_dm BIT(13)
+
+#define USB2_CAL_CTRL_ADDR (0x8 + USB2PHY_BASE)
+#define rb_usb2phy_pllcal_done BIT(31)
+#define rb_usb2phy_impcal_done BIT(23)
+
+#define USB2_PLL_CTRL0_ADDR (0x0 + USB2PHY_BASE)
+#define rb_usb2phy_pll_ready BIT(31)
+
+#define USB2_RX_CHAN_CTRL1_ADDR (0x18 + USB2PHY_BASE)
+#define rb_usb2phy_sqcal_done BIT(31)
+
+#define USB2_PHY2_CTRL_ADDR (0x804 + USB2PHY2_BASE)
+#define rb_usb2phy2_suspm BIT(7)
+#define rb_usb2phy2_pu BIT(0)
+#define USB2_PHY2_CAL_CTRL_ADDR (0x8 + USB2PHY2_BASE)
+#define USB2_PHY2_PLL_CTRL0_ADDR (0x0 + USB2PHY2_BASE)
+#define USB2_PHY2_RX_CHAN_CTRL1_ADDR (0x18 + USB2PHY2_BASE)
+
+#define USB2_PHY_BASE(usb32) (usb32 == 0 ? USB2PHY2_BASE : USB2PHY_BASE)
+#define USB2_PHY_CTRL_ADDR(usb32) \
+ (usb32 == 0 ? USB2_PHY2_CTRL_ADDR : USB2_OTG_PHY_CTRL_ADDR)
+#define RB_USB2PHY_SUSPM(usb32) \
+ (usb32 == 0 ? rb_usb2phy2_suspm : rb_usb2phy_suspm)
+#define RB_USB2PHY_PU(usb32) \
+ (usb32 == 0 ? rb_usb2phy2_pu : rb_usb2phy_pu)
+#define USB2_PHY_CAL_CTRL_ADDR(usb32) \
+ (usb32 == 0 ? USB2_PHY2_CAL_CTRL_ADDR : USB2_CAL_CTRL_ADDR)
+#define USB2_PHY_RX_CHAN_CTRL1_ADDR(usb32) \
+ (usb32 == 0 ? USB2_PHY2_RX_CHAN_CTRL1_ADDR : USB2_RX_CHAN_CTRL1_ADDR)
+#define USB2_PHY_PLL_CTRL0_ADDR(usb32) \
+ (usb32 == 0 ? USB2_PHY2_PLL_CTRL0_ADDR : USB2_PLL_CTRL0_ADDR)
+
+/*
+ * SATA definitions
+ */
+#define AHCI_BASE MVEBU_REG(0xE0000)
+
+#define rh_vsreg_addr (AHCI_BASE + 0x178)
+#define rh_vsreg_data (AHCI_BASE + 0x17C)
+#define rh_vs0_a (AHCI_BASE + 0xA0)
+#define rh_vs0_d (AHCI_BASE + 0xA4)
+
+#define vphy_sync_pattern_reg 0x224
+#define bs_txd_inv BIT(10)
+#define bs_rxd_inv BIT(11)
+
+#define vphy_loopback_reg0 0x223
+#define bs_phyintf_40bit 0x0C00
+#define bs_pll_ready_tx 0x10
+
+#define vphy_power_reg0 0x201
+
+#define vphy_calctl_reg 0x202
+#define bs_max_pll_rate BIT(12)
+
+#define vphy_reserve_reg 0x0e
+#define bs_phyctrl_frm_pin BIT(13)
+
+#define vsata_ctrl_reg 0x00
+#define bs_phy_pu_pll BIT(6)
+
+/*
+ * SDIO/eMMC definitions
+ */
+#define SDIO_BASE MVEBU_REG(0xD8000)
+
+#define SDIO_HOST_CTRL1_ADDR (SDIO_BASE + 0x28)
+#define SDIO_SDHC_FIFO_ADDR (SDIO_BASE + 0x12C)
+#define SDIO_CAP_12_ADDR (SDIO_BASE + 0x40)
+#define SDIO_ENDIAN_ADDR (SDIO_BASE + 0x1A4)
+#define SDIO_PHY_TIMING_ADDR (SDIO_BASE + 0x170)
+#define SDIO_PHY_PAD_CTRL0_ADDR (SDIO_BASE + 0x178)
+#define SDIO_DLL_RST_ADDR (SDIO_BASE + 0x148)
+
+#endif /* _COMPHY_A3700_H_ */
diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c
new file mode 100644
index 0000000000..344df3bed1
--- /dev/null
+++ b/drivers/phy/marvell/comphy_core.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+
+#include "comphy.h"
+
+#define COMPHY_MAX_CHIP 4
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char *get_speed_string(u32 speed)
+{
+ char *speed_strings[] = {"1.25 Gbps", "1.5 Gbps", "2.5 Gbps",
+ "3.0 Gbps", "3.125 Gbps", "5 Gbps", "6 Gbps",
+ "6.25 Gbps", "10.31 Gbps" };
+
+ if (speed < 0 || speed > PHY_SPEED_MAX)
+ return "invalid";
+
+ return speed_strings[speed];
+}
+
+static char *get_type_string(u32 type)
+{
+ char *type_strings[] = {"UNCONNECTED", "PEX0", "PEX1", "PEX2", "PEX3",
+ "SATA0", "SATA1", "SATA2", "SATA3", "SGMII0",
+ "SGMII1", "SGMII2", "SGMII3", "QSGMII",
+ "USB3_HOST0", "USB3_HOST1", "USB3_DEVICE",
+ "XAUI0", "XAUI1", "XAUI2", "XAUI3",
+ "RXAUI0", "RXAUI1", "KR"};
+
+ if (type < 0 || type > PHY_TYPE_MAX)
+ return "invalid";
+
+ return type_strings[type];
+}
+
+void reg_set(void __iomem *addr, u32 data, u32 mask)
+{
+ debug("Write to address = %#010lx, data = %#010x (mask = %#010x) - ",
+ (unsigned long)addr, data, mask);
+ debug("old value = %#010x ==> ", readl(addr));
+ reg_set_silent(addr, data, mask);
+ debug("new value %#010x\n", readl(addr));
+}
+
+void reg_set_silent(void __iomem *addr, u32 data, u32 mask)
+{
+ u32 reg_data;
+
+ reg_data = readl(addr);
+ reg_data &= ~mask;
+ reg_data |= data;
+ writel(reg_data, addr);
+}
+
+void reg_set16(void __iomem *addr, u16 data, u16 mask)
+{
+ debug("Write to address = %#010lx, data = %#06x (mask = %#06x) - ",
+ (unsigned long)addr, data, mask);
+ debug("old value = %#06x ==> ", readw(addr));
+ reg_set_silent16(addr, data, mask);
+ debug("new value %#06x\n", readw(addr));
+}
+
+void reg_set_silent16(void __iomem *addr, u16 data, u16 mask)
+{
+ u16 reg_data;
+
+ reg_data = readw(addr);
+ reg_data &= ~mask;
+ reg_data |= data;
+ writew(reg_data, addr);
+}
+
+void comphy_print(struct chip_serdes_phy_config *chip_cfg,
+ struct comphy_map *comphy_map_data)
+{
+ u32 lane;
+
+ for (lane = 0; lane < chip_cfg->comphy_lanes_count;
+ lane++, comphy_map_data++) {
+ if (comphy_map_data->type == PHY_TYPE_UNCONNECTED)
+ continue;
+
+ if (comphy_map_data->speed == PHY_SPEED_INVALID) {
+ printf("Comphy-%d: %-13s\n", lane,
+ get_type_string(comphy_map_data->type));
+ } else {
+ printf("Comphy-%d: %-13s %-10s\n", lane,
+ get_type_string(comphy_map_data->type),
+ get_speed_string(comphy_map_data->speed));
+ }
+ }
+}
+
+static int comphy_probe(struct udevice *dev)
+{
+ const void *blob = gd->fdt_blob;
+ int node = dev->of_offset;
+ struct chip_serdes_phy_config *chip_cfg = dev_get_priv(dev);
+ struct comphy_map comphy_map_data[MAX_LANE_OPTIONS];
+ int subnode;
+ int lane;
+
+ /* Save base addresses for later use */
+ chip_cfg->comphy_base_addr = (void *)dev_get_addr_index(dev, 0);
+ if (IS_ERR(chip_cfg->comphy_base_addr))
+ return PTR_ERR(chip_cfg->comphy_base_addr);
+
+ chip_cfg->hpipe3_base_addr = (void *)dev_get_addr_index(dev, 1);
+ if (IS_ERR(chip_cfg->hpipe3_base_addr))
+ return PTR_ERR(chip_cfg->hpipe3_base_addr);
+
+ chip_cfg->comphy_lanes_count = fdtdec_get_int(blob, node,
+ "max-lanes", 0);
+ if (chip_cfg->comphy_lanes_count <= 0) {
+ dev_err(&dev->dev, "comphy max lanes is wrong\n");
+ return -EINVAL;
+ }
+
+ chip_cfg->comphy_mux_bitcount = fdtdec_get_int(blob, node,
+ "mux-bitcount", 0);
+ if (chip_cfg->comphy_mux_bitcount <= 0) {
+ dev_err(&dev->dev, "comphy mux bit count is wrong\n");
+ return -EINVAL;
+ }
+
+ if (of_device_is_compatible(dev, "marvell,comphy-armada-3700"))
+ chip_cfg->ptr_comphy_chip_init = comphy_a3700_init;
+
+ if (of_device_is_compatible(dev, "marvell,comphy-cp110"))
+ chip_cfg->ptr_comphy_chip_init = comphy_cp110_init;
+
+ /*
+ * Bail out if no chip_init function is defined, e.g. no
+ * compatible node is found
+ */
+ if (!chip_cfg->ptr_comphy_chip_init) {
+ dev_err(&dev->dev, "comphy: No compatible DT node found\n");
+ return -ENODEV;
+ }
+
+ lane = 0;
+ fdt_for_each_subnode(blob, subnode, node) {
+ /* Skip disabled ports */
+ if (!fdtdec_get_is_enabled(blob, subnode))
+ continue;
+
+ comphy_map_data[lane].speed = fdtdec_get_int(
+ blob, subnode, "phy-speed", PHY_TYPE_INVALID);
+ comphy_map_data[lane].type = fdtdec_get_int(
+ blob, subnode, "phy-type", PHY_SPEED_INVALID);
+ comphy_map_data[lane].invert = fdtdec_get_int(
+ blob, subnode, "phy-invert", PHY_POLARITY_NO_INVERT);
+ comphy_map_data[lane].clk_src = fdtdec_get_bool(blob, subnode,
+ "clk-src");
+ if (comphy_map_data[lane].type == PHY_TYPE_INVALID) {
+ printf("no phy type for lane %d, setting lane as unconnected\n",
+ lane + 1);
+ }
+
+ lane++;
+ }
+
+ /* Save comphy index for MultiCP devices (A8K) */
+ chip_cfg->comphy_index = dev->seq;
+ /* PHY power UP sequence */
+ chip_cfg->ptr_comphy_chip_init(chip_cfg, comphy_map_data);
+ /* PHY print SerDes status */
+ comphy_print(chip_cfg, comphy_map_data);
+
+ /* Initialize dedicated PHYs (not muxed SerDes lanes) */
+ comphy_dedicated_phys_init();
+
+ return 0;
+}
+
+static const struct udevice_id comphy_ids[] = {
+ { .compatible = "marvell,mvebu-comphy" },
+ { }
+};
+
+U_BOOT_DRIVER(mvebu_comphy) = {
+ .name = "mvebu_comphy",
+ .id = UCLASS_MISC,
+ .of_match = comphy_ids,
+ .probe = comphy_probe,
+ .priv_auto_alloc_size = sizeof(struct chip_serdes_phy_config),
+};
diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c
new file mode 100644
index 0000000000..25c067d23f
--- /dev/null
+++ b/drivers/phy/marvell/comphy_cp110.c
@@ -0,0 +1,1726 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "comphy.h"
+#include "comphy_hpipe.h"
+#include "sata.h"
+#include "utmi_phy.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SD_ADDR(base, lane) (base + 0x1000 * lane)
+#define HPIPE_ADDR(base, lane) (SD_ADDR(base, lane) + 0x800)
+#define COMPHY_ADDR(base, lane) (base + 0x28 * lane)
+
+struct utmi_phy_data {
+ void __iomem *utmi_base_addr;
+ void __iomem *usb_cfg_addr;
+ void __iomem *utmi_cfg_addr;
+ u32 utmi_phy_port;
+};
+
+/*
+ * For CP-110 we have 2 Selector registers "PHY Selectors",
+ * and "PIPE Selectors".
+ * PIPE selector include USB and PCIe options.
+ * PHY selector include the Ethernet and SATA options, every Ethernet
+ * option has different options, for example: serdes lane2 had option
+ * Eth_port_0 that include (SGMII0, XAUI0, RXAUI0, KR)
+ */
+struct comphy_mux_data cp110_comphy_phy_mux_data[] = {
+ {4, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII2, 0x1}, /* Lane 0 */
+ {PHY_TYPE_XAUI2, 0x1}, {PHY_TYPE_SATA1, 0x4} } },
+ {4, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII3, 0x1}, /* Lane 1 */
+ {PHY_TYPE_XAUI3, 0x1}, {PHY_TYPE_SATA0, 0x4} } },
+ {6, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII0, 0x1}, /* Lane 2 */
+ {PHY_TYPE_XAUI0, 0x1}, {PHY_TYPE_RXAUI0, 0x1},
+ {PHY_TYPE_KR, 0x1}, {PHY_TYPE_SATA0, 0x4} } },
+ {8, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII0, 0x1}, /* Lane 3 */
+ {PHY_TYPE_XAUI0, 0x1}, {PHY_TYPE_RXAUI0, 0x1},
+ {PHY_TYPE_KR, 0x1}, {PHY_TYPE_XAUI1, 0x1},
+ {PHY_TYPE_RXAUI1, 0x1}, {PHY_TYPE_SATA1, 0x4} } },
+ {7, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII0, 0x2}, /* Lane 4 */
+ {PHY_TYPE_XAUI0, 0x1}, {PHY_TYPE_RXAUI0, 0x1}, {PHY_TYPE_KR, 0x1},
+ {PHY_TYPE_SGMII2, 0x1}, {PHY_TYPE_XAUI2, 0x1} } },
+ {6, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_XAUI1, 0x1}, /* Lane 5 */
+ {PHY_TYPE_RXAUI1, 0x1}, {PHY_TYPE_SGMII3, 0x1},
+ {PHY_TYPE_XAUI3, 0x1}, {PHY_TYPE_SATA1, 0x4} } },
+};
+
+struct comphy_mux_data cp110_comphy_pipe_mux_data[] = {
+ {2, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_PEX0, 0x4} } }, /* Lane 0 */
+ {4, {{PHY_TYPE_UNCONNECTED, 0x0}, /* Lane 1 */
+ {PHY_TYPE_USB3_HOST0, 0x1}, {PHY_TYPE_USB3_DEVICE, 0x2},
+ {PHY_TYPE_PEX0, 0x4} } },
+ {3, {{PHY_TYPE_UNCONNECTED, 0x0}, /* Lane 2 */
+ {PHY_TYPE_USB3_HOST0, 0x1}, {PHY_TYPE_PEX0, 0x4} } },
+ {3, {{PHY_TYPE_UNCONNECTED, 0x0}, /* Lane 3 */
+ {PHY_TYPE_USB3_HOST1, 0x1}, {PHY_TYPE_PEX0, 0x4} } },
+ {4, {{PHY_TYPE_UNCONNECTED, 0x0}, /* Lane 4 */
+ {PHY_TYPE_USB3_HOST1, 0x1},
+ {PHY_TYPE_USB3_DEVICE, 0x2}, {PHY_TYPE_PEX1, 0x4} } },
+ {2, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_PEX2, 0x4} } }, /* Lane 5 */
+};
+
+static u32 polling_with_timeout(void __iomem *addr, u32 val,
+ u32 mask, unsigned long usec_timout)
+{
+ u32 data;
+
+ do {
+ udelay(1);
+ data = readl(addr) & mask;
+ } while (data != val && --usec_timout > 0);
+
+ if (usec_timout == 0)
+ return data;
+
+ return 0;
+}
+
+static int comphy_pcie_power_up(u32 lane, u32 pcie_width,
+ bool clk_src, void __iomem *hpipe_base,
+ void __iomem *comphy_base)
+{
+ u32 mask, data, ret = 1;
+ void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane);
+ void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane);
+ void __iomem *addr;
+ u32 pcie_clk = 0; /* set input by default */
+
+ debug_enter();
+
+ /*
+ * ToDo:
+ * Add SAR (Sample-At-Reset) configuration for the PCIe clock
+ * direction. SAR code is currently not ported from Marvell
+ * U-Boot to mainline version.
+ *
+ * SerDes Lane 4/5 got the PCIe ref-clock #1,
+ * and SerDes Lane 0 got PCIe ref-clock #0
+ */
+ debug("PCIe clock = %x\n", pcie_clk);
+ debug("PCIe width = %d\n", pcie_width);
+
+ /* enable PCIe by4 and by2 */
+ if (lane == 0) {
+ if (pcie_width == 4) {
+ reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
+ 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET,
+ COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK);
+ } else if (pcie_width == 2) {
+ reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
+ 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET,
+ COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK);
+ }
+ }
+
+ /*
+ * If PCIe clock is output and clock source from SerDes lane 5,
+ * we need to configure the clock-source MUX.
+ * By default, the clock source is from lane 4
+ */
+ if (pcie_clk && clk_src && (lane == 5)) {
+ reg_set((void __iomem *)DFX_DEV_GEN_CTRL12,
+ 0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET,
+ DFX_DEV_GEN_PCIE_CLK_SRC_MASK);
+ }
+
+ debug("stage: RFU configurations - hard reset comphy\n");
+ /* RFU configurations - hard reset comphy */
+ mask = COMMON_PHY_CFG1_PWR_UP_MASK;
+ data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
+ mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
+ data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
+ mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
+ data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
+ mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
+ data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
+ mask |= COMMON_PHY_PHY_MODE_MASK;
+ data |= 0x0 << COMMON_PHY_PHY_MODE_OFFSET;
+ reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
+
+ /* release from hard reset */
+ mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
+ data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
+ mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
+ data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
+ reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
+
+ /* Wait 1ms - until band gap and ref clock ready */
+ mdelay(1);
+ /* Start comphy Configuration */
+ debug("stage: Comphy configuration\n");
+ /* Set PIPE soft reset */
+ mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK;
+ data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET;
+ /* Set PHY datapath width mode for V0 */
+ mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK;
+ data |= 0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET;
+ /* Set Data bus width USB mode for V0 */
+ mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK;
+ data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET;
+ /* Set CORE_CLK output frequency for 250Mhz */
+ mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK;
+ data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask);
+ /* Set PLL ready delay for 0x2 */
+ data = 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET;
+ mask = HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK;
+ if (pcie_width != 1) {
+ data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET;
+ mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK;
+ data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET;
+ mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK;
+ }
+ reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, data, mask);
+
+ /* Set PIPE mode interface to PCIe3 - 0x1 & set lane order */
+ data = 0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET;
+ mask = HPIPE_CLK_SRC_HI_MODE_PIPE_MASK;
+ if (pcie_width != 1) {
+ mask |= HPIPE_CLK_SRC_HI_LANE_STRT_MASK;
+ mask |= HPIPE_CLK_SRC_HI_LANE_MASTER_MASK;
+ mask |= HPIPE_CLK_SRC_HI_LANE_BREAK_MASK;
+ if (lane == 0) {
+ data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET;
+ data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET;
+ } else if (lane == (pcie_width - 1)) {
+ data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET;
+ }
+ }
+ reg_set(hpipe_addr + HPIPE_CLK_SRC_HI_REG, data, mask);
+ /* Config update polarity equalization */
+ reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG1_REG,
+ 0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET,
+ HPIPE_CFG_UPDATE_POLARITY_MASK);
+ /* Set PIPE version 4 to mode enable */
+ reg_set(hpipe_addr + HPIPE_DFE_CTRL_28_REG,
+ 0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET,
+ HPIPE_DFE_CTRL_28_PIPE4_MASK);
+ /* TODO: check if pcie clock is output/input - for bringup use input*/
+ /* Enable PIN clock 100M_125M */
+ mask = 0;
+ data = 0;
+ /* Only if clock is output, configure the clock-source mux */
+ if (pcie_clk) {
+ mask |= HPIPE_MISC_CLK100M_125M_MASK;
+ data |= 0x1 << HPIPE_MISC_CLK100M_125M_OFFSET;
+ }
+ /*
+ * Set PIN_TXDCLK_2X Clock Frequency Selection for outputs 500MHz
+ * clock
+ */
+ mask |= HPIPE_MISC_TXDCLK_2X_MASK;
+ data |= 0x0 << HPIPE_MISC_TXDCLK_2X_OFFSET;
+ /* Enable 500MHz Clock */
+ mask |= HPIPE_MISC_CLK500_EN_MASK;
+ data |= 0x1 << HPIPE_MISC_CLK500_EN_OFFSET;
+ if (pcie_clk) { /* output */
+ /* Set reference clock comes from group 1 */
+ mask |= HPIPE_MISC_REFCLK_SEL_MASK;
+ data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
+ } else {
+ /* Set reference clock comes from group 2 */
+ mask |= HPIPE_MISC_REFCLK_SEL_MASK;
+ data |= 0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET;
+ }
+ reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
+ if (pcie_clk) { /* output */
+ /* Set reference frequcency select - 0x2 for 25MHz*/
+ mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
+ data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
+ } else {
+ /* Set reference frequcency select - 0x0 for 100MHz*/
+ mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
+ data = 0x0 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
+ }
+ /* Set PHY mode to PCIe */
+ mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
+ data |= 0x3 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
+
+ /* ref clock alignment */
+ if (pcie_width != 1) {
+ mask = HPIPE_LANE_ALIGN_OFF_MASK;
+ data = 0x0 << HPIPE_LANE_ALIGN_OFF_OFFSET;
+ reg_set(hpipe_addr + HPIPE_LANE_ALIGN_REG, data, mask);
+ }
+
+ /*
+ * Set the amount of time spent in the LoZ state - set for 0x7 only if
+ * the PCIe clock is output
+ */
+ if (pcie_clk) {
+ reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL,
+ 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET,
+ HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK);
+ }
+
+ /* Set Maximal PHY Generation Setting(8Gbps) */
+ mask = HPIPE_INTERFACE_GEN_MAX_MASK;
+ data = 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET;
+ /* Set Link Train Mode (Tx training control pins are used) */
+ mask |= HPIPE_INTERFACE_LINK_TRAIN_MASK;
+ data |= 0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_INTERFACE_REG, data, mask);
+
+ /* Set Idle_sync enable */
+ mask = HPIPE_PCIE_IDLE_SYNC_MASK;
+ data = 0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET;
+ /* Select bits for PCIE Gen3(32bit) */
+ mask |= HPIPE_PCIE_SEL_BITS_MASK;
+ data |= 0x2 << HPIPE_PCIE_SEL_BITS_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PCIE_REG0, data, mask);
+
+ /* Enable Tx_adapt_g1 */
+ mask = HPIPE_TX_TRAIN_CTRL_G1_MASK;
+ data = 0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET;
+ /* Enable Tx_adapt_gn1 */
+ mask |= HPIPE_TX_TRAIN_CTRL_GN1_MASK;
+ data |= 0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET;
+ /* Disable Tx_adapt_g0 */
+ mask |= HPIPE_TX_TRAIN_CTRL_G0_MASK;
+ data |= 0x0 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask);
+
+ /* Set reg_tx_train_chk_init */
+ mask = HPIPE_TX_TRAIN_CHK_INIT_MASK;
+ data = 0x0 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET;
+ /* Enable TX_COE_FM_PIN_PCIE3_EN */
+ mask |= HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK;
+ data |= 0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask);
+
+ debug("stage: TRx training parameters\n");
+ /* Set Preset sweep configurations */
+ mask = HPIPE_TX_TX_STATUS_CHECK_MODE_MASK;
+ data = 0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET;
+
+ mask |= HPIPE_TX_NUM_OF_PRESET_MASK;
+ data |= 0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET;
+
+ mask |= HPIPE_TX_SWEEP_PRESET_EN_MASK;
+ data |= 0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_11_REG, data, mask);
+
+ /* Tx train start configuration */
+ mask = HPIPE_TX_TRAIN_START_SQ_EN_MASK;
+ data = 0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET;
+
+ mask |= HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK;
+ data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET;
+
+ mask |= HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK;
+ data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET;
+
+ mask |= HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK;
+ data |= 0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask);
+
+ /* Enable Tx train P2P */
+ mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK;
+ data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask);
+
+ /* Configure Tx train timeout */
+ mask = HPIPE_TRX_TRAIN_TIMER_MASK;
+ data = 0x17 << HPIPE_TRX_TRAIN_TIMER_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_4_REG, data, mask);
+
+ /* Disable G0/G1/GN1 adaptation */
+ mask = HPIPE_TX_TRAIN_CTRL_G1_MASK | HPIPE_TX_TRAIN_CTRL_GN1_MASK
+ | HPIPE_TX_TRAIN_CTRL_G0_OFFSET;
+ data = 0;
+ reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask);
+
+ /* Disable DTL frequency loop */
+ mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
+ data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
+
+ /* Configure G3 DFE */
+ mask = HPIPE_G3_DFE_RES_MASK;
+ data = 0x3 << HPIPE_G3_DFE_RES_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask);
+
+ /* Force DFE resolution (use GEN table value) */
+ mask = HPIPE_DFE_RES_FORCE_MASK;
+ data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
+
+ /* Configure initial and final coefficient value for receiver */
+ mask = HPIPE_G3_RX_SELMUPI_MASK;
+ data = 0x1 << HPIPE_G3_RX_SELMUPI_OFFSET;
+
+ mask |= HPIPE_G3_RX_SELMUPF_MASK;
+ data |= 0x1 << HPIPE_G3_RX_SELMUPF_OFFSET;
+
+ mask |= HPIPE_G3_SETTING_BIT_MASK;
+ data |= 0x0 << HPIPE_G3_SETTING_BIT_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G3_SETTINGS_1_REG, data, mask);
+
+ /* Trigger sampler enable pulse */
+ mask = HPIPE_SMAPLER_MASK;
+ data = 0x1 << HPIPE_SMAPLER_OFFSET;
+ reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
+ udelay(5);
+ reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, 0, mask);
+
+ /* FFE resistor tuning for different bandwidth */
+ mask = HPIPE_G3_FFE_DEG_RES_LEVEL_MASK;
+ data = 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET;
+
+ mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK;
+ data |= 0x1 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask);
+
+ /* Set phy in root complex mode */
+ mask = HPIPE_CFG_PHY_RC_EP_MASK;
+ data = 0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET;
+ reg_set(hpipe_addr + HPIPE_LANE_EQU_CONFIG_0_REG, data, mask);
+
+ debug("stage: Comphy power up\n");
+
+ /*
+ * For PCIe by4 or by2 - release from reset only after finish to
+ * configure all lanes
+ */
+ if ((pcie_width == 1) || (lane == (pcie_width - 1))) {
+ u32 i, start_lane, end_lane;
+
+ if (pcie_width != 1) {
+ /* allows writing to all lanes in one write */
+ reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
+ 0x0 <<
+ COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET,
+ COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK);
+ start_lane = 0;
+ end_lane = pcie_width;
+
+ /*
+ * Release from PIPE soft reset
+ * for PCIe by4 or by2 - release from soft reset
+ * all lanes - can't use read modify write
+ */
+ reg_set(HPIPE_ADDR(hpipe_base, 0) +
+ HPIPE_RST_CLK_CTRL_REG, 0x24, 0xffffffff);
+ } else {
+ start_lane = lane;
+ end_lane = lane + 1;
+
+ /*
+ * Release from PIPE soft reset
+ * for PCIe by4 or by2 - release from soft reset
+ * all lanes
+ */
+ reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG,
+ 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET,
+ HPIPE_RST_CLK_CTRL_PIPE_RST_MASK);
+ }
+
+
+ if (pcie_width != 1) {
+ /* disable writing to all lanes with one write */
+ reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
+ 0x3210 <<
+ COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET,
+ COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK);
+ }
+
+ debug("stage: Check PLL\n");
+ /* Read lane status */
+ for (i = start_lane; i < end_lane; i++) {
+ addr = HPIPE_ADDR(hpipe_base, i) +
+ HPIPE_LANE_STATUS1_REG;
+ data = HPIPE_LANE_STATUS1_PCLK_EN_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 15000);
+ if (data != 0) {
+ debug("Read from reg = %p - value = 0x%x\n",
+ hpipe_addr + HPIPE_LANE_STATUS1_REG,
+ data);
+ error("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n");
+ ret = 0;
+ }
+ }
+ }
+
+ debug_exit();
+ return ret;
+}
+
+static int comphy_usb3_power_up(u32 lane, void __iomem *hpipe_base,
+ void __iomem *comphy_base)
+{
+ u32 mask, data, ret = 1;
+ void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane);
+ void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane);
+ void __iomem *addr;
+
+ debug_enter();
+ debug("stage: RFU configurations - hard reset comphy\n");
+ /* RFU configurations - hard reset comphy */
+ mask = COMMON_PHY_CFG1_PWR_UP_MASK;
+ data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
+ mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
+ data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
+ mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
+ data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
+ mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
+ data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
+ mask |= COMMON_PHY_PHY_MODE_MASK;
+ data |= 0x1 << COMMON_PHY_PHY_MODE_OFFSET;
+ reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
+
+ /* release from hard reset */
+ mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
+ data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
+ mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
+ data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
+ reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
+
+ /* Wait 1ms - until band gap and ref clock ready */
+ mdelay(1);
+
+ /* Start comphy Configuration */
+ debug("stage: Comphy configuration\n");
+ /* Set PIPE soft reset */
+ mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK;
+ data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET;
+ /* Set PHY datapath width mode for V0 */
+ mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK;
+ data |= 0x0 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET;
+ /* Set Data bus width USB mode for V0 */
+ mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK;
+ data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET;
+ /* Set CORE_CLK output frequency for 250Mhz */
+ mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK;
+ data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask);
+ /* Set PLL ready delay for 0x2 */
+ reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG,
+ 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET,
+ HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK);
+ /* Set reference clock to come from group 1 - 25Mhz */
+ reg_set(hpipe_addr + HPIPE_MISC_REG,
+ 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET,
+ HPIPE_MISC_REFCLK_SEL_MASK);
+ /* Set reference frequcency select - 0x2 */
+ mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
+ data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
+ /* Set PHY mode to USB - 0x5 */
+ mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
+ data |= 0x5 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
+ /* Set the amount of time spent in the LoZ state - set for 0x7 */
+ reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL,
+ 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET,
+ HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK);
+ /* Set max PHY generation setting - 5Gbps */
+ reg_set(hpipe_addr + HPIPE_INTERFACE_REG,
+ 0x1 << HPIPE_INTERFACE_GEN_MAX_OFFSET,
+ HPIPE_INTERFACE_GEN_MAX_MASK);
+ /* Set select data width 20Bit (SEL_BITS[2:0]) */
+ reg_set(hpipe_addr + HPIPE_LOOPBACK_REG,
+ 0x1 << HPIPE_LOOPBACK_SEL_OFFSET,
+ HPIPE_LOOPBACK_SEL_MASK);
+ /* select de-emphasize 3.5db */
+ reg_set(hpipe_addr + HPIPE_LANE_CONFIG0_REG,
+ 0x1 << HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET,
+ HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK);
+ /* override tx margining from the MAC */
+ reg_set(hpipe_addr + HPIPE_TST_MODE_CTRL_REG,
+ 0x1 << HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET,
+ HPIPE_TST_MODE_CTRL_MODE_MARGIN_MASK);
+
+ /* Start analog paramters from ETP(HW) */
+ debug("stage: Analog paramters from ETP(HW)\n");
+ /* Set Pin DFE_PAT_DIS -> Bit[1]: PIN_DFE_PAT_DIS = 0x0 */
+ mask = HPIPE_LANE_CFG4_DFE_CTRL_MASK;
+ data = 0x1 << HPIPE_LANE_CFG4_DFE_CTRL_OFFSET;
+ /* Set Override PHY DFE control pins for 0x1 */
+ mask |= HPIPE_LANE_CFG4_DFE_OVER_MASK;
+ data |= 0x1 << HPIPE_LANE_CFG4_DFE_OVER_OFFSET;
+ /* Set Spread Spectrum Clock Enable fot 0x1 */
+ mask |= HPIPE_LANE_CFG4_SSC_CTRL_MASK;
+ data |= 0x1 << HPIPE_LANE_CFG4_SSC_CTRL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask);
+ /* End of analog parameters */
+
+ debug("stage: Comphy power up\n");
+ /* Release from PIPE soft reset */
+ reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG,
+ 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET,
+ HPIPE_RST_CLK_CTRL_PIPE_RST_MASK);
+
+ /* wait 15ms - for comphy calibration done */
+ debug("stage: Check PLL\n");
+ /* Read lane status */
+ addr = hpipe_addr + HPIPE_LANE_STATUS1_REG;
+ data = HPIPE_LANE_STATUS1_PCLK_EN_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 15000);
+ if (data != 0) {
+ debug("Read from reg = %p - value = 0x%x\n",
+ hpipe_addr + HPIPE_LANE_STATUS1_REG, data);
+ error("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n");
+ ret = 0;
+ }
+
+ debug_exit();
+ return ret;
+}
+
+static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base,
+ void __iomem *comphy_base, int comphy_index)
+{
+ u32 mask, data, i, ret = 1;
+ void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane);
+ void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane);
+ void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane);
+ void __iomem *addr;
+ void __iomem *sata_base = NULL;
+ int sata_node = -1; /* Set to -1 in order to read the first sata node */
+
+ debug_enter();
+
+ /*
+ * Assumption - each CP has only one SATA controller
+ * Calling fdt_node_offset_by_compatible first time (with sata_node = -1
+ * will return the first node always.
+ * In order to parse each CPs SATA node, fdt_node_offset_by_compatible
+ * must be called again (according to the CP id)
+ */
+ for (i = 0; i < (comphy_index + 1); i++)
+ sata_node = fdt_node_offset_by_compatible(
+ gd->fdt_blob, sata_node, "marvell,armada-8k-ahci");
+
+ if (sata_node == 0) {
+ error("SATA node not found in FDT\n");
+ return 0;
+ }
+
+ sata_base = (void __iomem *)fdtdec_get_addr_size_auto_noparent(
+ gd->fdt_blob, sata_node, "reg", 0, NULL, true);
+ if (sata_base == NULL) {
+ error("SATA address not found in FDT\n");
+ return 0;
+ }
+
+ debug("SATA address found in FDT %p\n", sata_base);
+
+ debug("stage: MAC configuration - power down comphy\n");
+ /*
+ * MAC configuration powe down comphy use indirect address for
+ * vendor spesific SATA control register
+ */
+ reg_set(sata_base + SATA3_VENDOR_ADDRESS,
+ SATA_CONTROL_REG << SATA3_VENDOR_ADDR_OFSSET,
+ SATA3_VENDOR_ADDR_MASK);
+ /* SATA 0 power down */
+ mask = SATA3_CTRL_SATA0_PD_MASK;
+ data = 0x1 << SATA3_CTRL_SATA0_PD_OFFSET;
+ /* SATA 1 power down */
+ mask |= SATA3_CTRL_SATA1_PD_MASK;
+ data |= 0x1 << SATA3_CTRL_SATA1_PD_OFFSET;
+ /* SATA SSU disable */
+ mask |= SATA3_CTRL_SATA1_ENABLE_MASK;
+ data |= 0x0 << SATA3_CTRL_SATA1_ENABLE_OFFSET;
+ /* SATA port 1 disable */
+ mask |= SATA3_CTRL_SATA_SSU_MASK;
+ data |= 0x0 << SATA3_CTRL_SATA_SSU_OFFSET;
+ reg_set(sata_base + SATA3_VENDOR_DATA, data, mask);
+
+ debug("stage: RFU configurations - hard reset comphy\n");
+ /* RFU configurations - hard reset comphy */
+ mask = COMMON_PHY_CFG1_PWR_UP_MASK;
+ data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
+ mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
+ data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
+ mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
+ data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
+ mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
+ data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
+ reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
+
+ /* Set select data width 40Bit - SATA mode only */
+ reg_set(comphy_addr + COMMON_PHY_CFG6_REG,
+ 0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET,
+ COMMON_PHY_CFG6_IF_40_SEL_MASK);
+
+ /* release from hard reset in SD external */
+ mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
+ data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+ /* Wait 1ms - until band gap and ref clock ready */
+ mdelay(1);
+
+ debug("stage: Comphy configuration\n");
+ /* Start comphy Configuration */
+ /* Set reference clock to comes from group 1 - choose 25Mhz */
+ reg_set(hpipe_addr + HPIPE_MISC_REG,
+ 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET,
+ HPIPE_MISC_REFCLK_SEL_MASK);
+ /* Reference frequency select set 1 (for SATA = 25Mhz) */
+ mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
+ data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
+ /* PHY mode select (set SATA = 0x0 */
+ mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
+ data |= 0x0 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
+ /* Set max PHY generation setting - 6Gbps */
+ reg_set(hpipe_addr + HPIPE_INTERFACE_REG,
+ 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET,
+ HPIPE_INTERFACE_GEN_MAX_MASK);
+ /* Set select data width 40Bit (SEL_BITS[2:0]) */
+ reg_set(hpipe_addr + HPIPE_LOOPBACK_REG,
+ 0x2 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK);
+
+ debug("stage: Analog paramters from ETP(HW)\n");
+ /*
+ * TODO: Set analog paramters from ETP(HW) - for now use the
+ * default datas
+ */
+
+ /* DFE reset sequence */
+ reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
+ 0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET,
+ HPIPE_PWR_CTR_RST_DFE_MASK);
+ reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
+ 0x0 << HPIPE_PWR_CTR_RST_DFE_OFFSET,
+ HPIPE_PWR_CTR_RST_DFE_MASK);
+ /* SW reset for interupt logic */
+ reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
+ 0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET,
+ HPIPE_PWR_CTR_SFT_RST_MASK);
+ reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
+ 0x0 << HPIPE_PWR_CTR_SFT_RST_OFFSET,
+ HPIPE_PWR_CTR_SFT_RST_MASK);
+
+ debug("stage: Comphy power up\n");
+ /*
+ * MAC configuration power up comphy - power up PLL/TX/RX
+ * use indirect address for vendor spesific SATA control register
+ */
+ reg_set(sata_base + SATA3_VENDOR_ADDRESS,
+ SATA_CONTROL_REG << SATA3_VENDOR_ADDR_OFSSET,
+ SATA3_VENDOR_ADDR_MASK);
+ /* SATA 0 power up */
+ mask = SATA3_CTRL_SATA0_PD_MASK;
+ data = 0x0 << SATA3_CTRL_SATA0_PD_OFFSET;
+ /* SATA 1 power up */
+ mask |= SATA3_CTRL_SATA1_PD_MASK;
+ data |= 0x0 << SATA3_CTRL_SATA1_PD_OFFSET;
+ /* SATA SSU enable */
+ mask |= SATA3_CTRL_SATA1_ENABLE_MASK;
+ data |= 0x1 << SATA3_CTRL_SATA1_ENABLE_OFFSET;
+ /* SATA port 1 enable */
+ mask |= SATA3_CTRL_SATA_SSU_MASK;
+ data |= 0x1 << SATA3_CTRL_SATA_SSU_OFFSET;
+ reg_set(sata_base + SATA3_VENDOR_DATA, data, mask);
+
+ /* MBUS request size and interface select register */
+ reg_set(sata_base + SATA3_VENDOR_ADDRESS,
+ SATA_MBUS_SIZE_SELECT_REG << SATA3_VENDOR_ADDR_OFSSET,
+ SATA3_VENDOR_ADDR_MASK);
+ /* Mbus regret enable */
+ reg_set(sata_base + SATA3_VENDOR_DATA,
+ 0x1 << SATA_MBUS_REGRET_EN_OFFSET, SATA_MBUS_REGRET_EN_MASK);
+
+ debug("stage: Check PLL\n");
+
+ addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
+ data = SD_EXTERNAL_STATUS0_PLL_TX_MASK &
+ SD_EXTERNAL_STATUS0_PLL_RX_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 15000);
+ if (data != 0) {
+ debug("Read from reg = %p - value = 0x%x\n",
+ hpipe_addr + HPIPE_LANE_STATUS1_REG, data);
+ error("SD_EXTERNAL_STATUS0_PLL_TX is %d, SD_EXTERNAL_STATUS0_PLL_RX is %d\n",
+ (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK),
+ (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK));
+ ret = 0;
+ }
+
+ debug_exit();
+ return ret;
+}
+
+static int comphy_sgmii_power_up(u32 lane, u32 sgmii_speed,
+ void __iomem *hpipe_base,
+ void __iomem *comphy_base)
+{
+ u32 mask, data, ret = 1;
+ void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane);
+ void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane);
+ void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane);
+ void __iomem *addr;
+
+ debug_enter();
+ debug("stage: RFU configurations - hard reset comphy\n");
+ /* RFU configurations - hard reset comphy */
+ mask = COMMON_PHY_CFG1_PWR_UP_MASK;
+ data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
+ mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
+ data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
+ reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
+
+ /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */
+ mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
+ data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK;
+ if (sgmii_speed == PHY_SPEED_1_25G) {
+ data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
+ data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
+ } else {
+ /* 3.125G */
+ data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
+ data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
+ }
+ mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
+ data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
+ data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK;
+ data |= 1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
+
+ /* release from hard reset */
+ mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
+ data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
+ data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
+ data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+ /* release from hard reset */
+ mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
+ data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+
+ /* Wait 1ms - until band gap and ref clock ready */
+ mdelay(1);
+
+ /* Start comphy Configuration */
+ debug("stage: Comphy configuration\n");
+ /* set reference clock */
+ mask = HPIPE_MISC_REFCLK_SEL_MASK;
+ data = 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
+ /* Power and PLL Control */
+ mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
+ data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
+ mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
+ data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
+ /* Loopback register */
+ mask = HPIPE_LOOPBACK_SEL_MASK;
+ data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask);
+ /* rx control 1 */
+ mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK;
+ data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET;
+ mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK;
+ data |= 0x0 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask);
+ /* DTL Control */
+ mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
+ data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
+
+ /* Set analog paramters from ETP(HW) - for now use the default datas */
+ debug("stage: Analog paramters from ETP(HW)\n");
+
+ reg_set(hpipe_addr + HPIPE_G1_SET_0_REG,
+ 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET,
+ HPIPE_G1_SET_0_G1_TX_EMPH1_MASK);
+
+ debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n");
+ /* SERDES External Configuration */
+ mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
+ data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
+
+ /* check PLL rx & tx ready */
+ addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
+ data = SD_EXTERNAL_STATUS0_PLL_RX_MASK |
+ SD_EXTERNAL_STATUS0_PLL_TX_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 15000);
+ if (data != 0) {
+ debug("Read from reg = %p - value = 0x%x\n",
+ sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
+ error("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n",
+ (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK),
+ (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK));
+ ret = 0;
+ }
+
+ /* RX init */
+ mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
+ data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+ /* check that RX init done */
+ addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
+ data = SD_EXTERNAL_STATUS0_RX_INIT_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 100);
+ if (data != 0) {
+ debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
+ error("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
+ ret = 0;
+ }
+
+ debug("stage: RF Reset\n");
+ /* RF Reset */
+ mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
+ data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+ debug_exit();
+ return ret;
+}
+
+static int comphy_kr_power_up(u32 lane, void __iomem *hpipe_base,
+ void __iomem *comphy_base)
+{
+ u32 mask, data, ret = 1;
+ void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane);
+ void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane);
+ void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane);
+ void __iomem *addr;
+
+ debug_enter();
+ debug("stage: RFU configurations - hard reset comphy\n");
+ /* RFU configurations - hard reset comphy */
+ mask = COMMON_PHY_CFG1_PWR_UP_MASK;
+ data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
+ mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
+ data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
+ reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
+
+ /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */
+ mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
+ data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK;
+ data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK;
+ data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
+ data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
+ data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK;
+ data |= 0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
+
+ /* release from hard reset */
+ mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
+ data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
+ data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
+ data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+ mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
+ data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+
+ /* Wait 1ms - until band gap and ref clock ready */
+ mdelay(1);
+
+ /* Start comphy Configuration */
+ debug("stage: Comphy configuration\n");
+ /* set reference clock */
+ mask = HPIPE_MISC_ICP_FORCE_MASK;
+ data = 0x1 << HPIPE_MISC_ICP_FORCE_OFFSET;
+ mask |= HPIPE_MISC_REFCLK_SEL_MASK;
+ data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
+ /* Power and PLL Control */
+ mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
+ data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
+ mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
+ data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
+ /* Loopback register */
+ mask = HPIPE_LOOPBACK_SEL_MASK;
+ data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask);
+ /* rx control 1 */
+ mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK;
+ data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET;
+ mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK;
+ data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask);
+ /* DTL Control */
+ mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
+ data = 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
+
+ /* Set analog paramters from ETP(HW) */
+ debug("stage: Analog paramters from ETP(HW)\n");
+ /* SERDES External Configuration 2 */
+ mask = SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK;
+ data = 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask);
+ /* 0x7-DFE Resolution control */
+ mask = HPIPE_DFE_RES_FORCE_MASK;
+ data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
+ /* 0xd-G1_Setting_0 */
+ mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK;
+ data = 0x1c << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET;
+ mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK;
+ data |= 0xe << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask);
+ /* Genration 1 setting 2 (G1_Setting_2) */
+ mask = HPIPE_G1_SET_2_G1_TX_EMPH0_MASK;
+ data = 0x0 << HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET;
+ mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK;
+ data |= 0x1 << HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask);
+ /* Transmitter Slew Rate Control register (tx_reg1) */
+ mask = HPIPE_TX_REG1_TX_EMPH_RES_MASK;
+ data = 0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET;
+ mask |= HPIPE_TX_REG1_SLC_EN_MASK;
+ data |= 0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TX_REG1_REG, data, mask);
+ /* Impedance Calibration Control register (cal_reg1) */
+ mask = HPIPE_CAL_REG_1_EXT_TXIMP_MASK;
+ data = 0xe << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET;
+ mask |= HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK;
+ data |= 0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_CAL_REG1_REG, data, mask);
+ /* Generation 1 Setting 5 (g1_setting_5) */
+ mask = HPIPE_G1_SETTING_5_G1_ICP_MASK;
+ data = 0 << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G1_SETTING_5_REG, data, mask);
+ /* 0xE-G1_Setting_1 */
+ mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
+ data = 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
+ mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK;
+ data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET;
+ mask |= HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK;
+ data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask);
+ /* 0xA-DFE_Reg3 */
+ mask = HPIPE_DFE_F3_F5_DFE_EN_MASK;
+ data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET;
+ mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK;
+ data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask);
+
+ /* 0x111-G1_Setting_4 */
+ mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK;
+ data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
+ /* Genration 1 setting 3 (G1_Setting_3) */
+ mask = HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK;
+ data = 0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
+
+ debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n");
+ /* SERDES External Configuration */
+ mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
+ data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
+
+
+ /* check PLL rx & tx ready */
+ addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
+ data = SD_EXTERNAL_STATUS0_PLL_RX_MASK |
+ SD_EXTERNAL_STATUS0_PLL_TX_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 15000);
+ if (data != 0) {
+ debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
+ error("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n",
+ (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK),
+ (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK));
+ ret = 0;
+ }
+
+ /* RX init */
+ mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
+ data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+
+ /* check that RX init done */
+ addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
+ data = SD_EXTERNAL_STATUS0_RX_INIT_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 100);
+ if (data != 0) {
+ debug("Read from reg = %p - value = 0x%x\n",
+ sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
+ error("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
+ ret = 0;
+ }
+
+ debug("stage: RF Reset\n");
+ /* RF Reset */
+ mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
+ data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+ debug_exit();
+ return ret;
+}
+
+static int comphy_rxauii_power_up(u32 lane, void __iomem *hpipe_base,
+ void __iomem *comphy_base)
+{
+ u32 mask, data, ret = 1;
+ void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane);
+ void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane);
+ void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane);
+ void __iomem *addr;
+
+ debug_enter();
+ debug("stage: RFU configurations - hard reset comphy\n");
+ /* RFU configurations - hard reset comphy */
+ mask = COMMON_PHY_CFG1_PWR_UP_MASK;
+ data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
+ mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
+ data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
+ reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
+
+ if (lane == 2) {
+ reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
+ 0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET,
+ COMMON_PHY_SD_CTRL1_RXAUI0_MASK);
+ }
+ if (lane == 4) {
+ reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
+ 0x1 << COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET,
+ COMMON_PHY_SD_CTRL1_RXAUI1_MASK);
+ }
+
+ /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */
+ mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
+ data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK;
+ data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK;
+ data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
+ data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
+ data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK;
+ data |= 0x0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_MEDIA_MODE_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
+
+ /* release from hard reset */
+ mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
+ data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
+ data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
+ data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+ mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
+ data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+ /* Wait 1ms - until band gap and ref clock ready */
+ mdelay(1);
+
+ /* Start comphy Configuration */
+ debug("stage: Comphy configuration\n");
+ /* set reference clock */
+ reg_set(hpipe_addr + HPIPE_MISC_REG,
+ 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET,
+ HPIPE_MISC_REFCLK_SEL_MASK);
+ /* Power and PLL Control */
+ mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
+ data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
+ mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
+ data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
+ /* Loopback register */
+ reg_set(hpipe_addr + HPIPE_LOOPBACK_REG,
+ 0x1 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK);
+ /* rx control 1 */
+ mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK;
+ data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET;
+ mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK;
+ data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask);
+ /* DTL Control */
+ reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG,
+ 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET,
+ HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK);
+
+ /* Set analog paramters from ETP(HW) */
+ debug("stage: Analog paramters from ETP(HW)\n");
+ /* SERDES External Configuration 2 */
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG,
+ 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET,
+ SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK);
+ /* 0x7-DFE Resolution control */
+ reg_set(hpipe_addr + HPIPE_DFE_REG0, 0x1 << HPIPE_DFE_RES_FORCE_OFFSET,
+ HPIPE_DFE_RES_FORCE_MASK);
+ /* 0xd-G1_Setting_0 */
+ reg_set(hpipe_addr + HPIPE_G1_SET_0_REG,
+ 0xd << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET,
+ HPIPE_G1_SET_0_G1_TX_EMPH1_MASK);
+ /* 0xE-G1_Setting_1 */
+ mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
+ data = 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
+ mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK;
+ data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET;
+ mask |= HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK;
+ data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask);
+ /* 0xA-DFE_Reg3 */
+ mask = HPIPE_DFE_F3_F5_DFE_EN_MASK;
+ data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET;
+ mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK;
+ data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask);
+
+ /* 0x111-G1_Setting_4 */
+ mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK;
+ data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
+
+ debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n");
+ /* SERDES External Configuration */
+ mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
+ data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
+
+
+ /* check PLL rx & tx ready */
+ addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
+ data = SD_EXTERNAL_STATUS0_PLL_RX_MASK |
+ SD_EXTERNAL_STATUS0_PLL_TX_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 15000);
+ if (data != 0) {
+ debug("Read from reg = %p - value = 0x%x\n",
+ sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
+ error("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n",
+ (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK),
+ (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK));
+ ret = 0;
+ }
+
+ /* RX init */
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG,
+ 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET,
+ SD_EXTERNAL_CONFIG1_RX_INIT_MASK);
+
+ /* check that RX init done */
+ addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
+ data = SD_EXTERNAL_STATUS0_RX_INIT_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 100);
+ if (data != 0) {
+ debug("Read from reg = %p - value = 0x%x\n",
+ sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
+ error("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
+ ret = 0;
+ }
+
+ debug("stage: RF Reset\n");
+ /* RF Reset */
+ mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
+ data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+ debug_exit();
+ return ret;
+}
+
+static void comphy_utmi_power_down(u32 utmi_index, void __iomem *utmi_base_addr,
+ void __iomem *usb_cfg_addr,
+ void __iomem *utmi_cfg_addr,
+ u32 utmi_phy_port)
+{
+ u32 mask, data;
+
+ debug_enter();
+ debug("stage: UTMI %d - Power down transceiver (power down Phy), Power down PLL, and SuspendDM\n",
+ utmi_index);
+ /* Power down UTMI PHY */
+ reg_set(utmi_cfg_addr, 0x0 << UTMI_PHY_CFG_PU_OFFSET,
+ UTMI_PHY_CFG_PU_MASK);
+
+ /*
+ * If UTMI connected to USB Device, configure mux prior to PHY init
+ * (Device can be connected to UTMI0 or to UTMI1)
+ */
+ if (utmi_phy_port == UTMI_PHY_TO_USB_DEVICE0) {
+ debug("stage: UTMI %d - Enable Device mode and configure UTMI mux\n",
+ utmi_index);
+ /* USB3 Device UTMI enable */
+ mask = UTMI_USB_CFG_DEVICE_EN_MASK;
+ data = 0x1 << UTMI_USB_CFG_DEVICE_EN_OFFSET;
+ /* USB3 Device UTMI MUX */
+ mask |= UTMI_USB_CFG_DEVICE_MUX_MASK;
+ data |= utmi_index << UTMI_USB_CFG_DEVICE_MUX_OFFSET;
+ reg_set(usb_cfg_addr, data, mask);
+ }
+
+ /* Set Test suspendm mode */
+ mask = UTMI_CTRL_STATUS0_SUSPENDM_MASK;
+ data = 0x1 << UTMI_CTRL_STATUS0_SUSPENDM_OFFSET;
+ /* Enable Test UTMI select */
+ mask |= UTMI_CTRL_STATUS0_TEST_SEL_MASK;
+ data |= 0x1 << UTMI_CTRL_STATUS0_TEST_SEL_OFFSET;
+ reg_set(utmi_base_addr + UTMI_CTRL_STATUS0_REG, data, mask);
+
+ /* Wait for UTMI power down */
+ mdelay(1);
+
+ debug_exit();
+ return;
+}
+
+static void comphy_utmi_phy_config(u32 utmi_index, void __iomem *utmi_base_addr,
+ void __iomem *usb_cfg_addr,
+ void __iomem *utmi_cfg_addr,
+ u32 utmi_phy_port)
+{
+ u32 mask, data;
+
+ debug_exit();
+ debug("stage: Configure UTMI PHY %d registers\n", utmi_index);
+ /* Reference Clock Divider Select */
+ mask = UTMI_PLL_CTRL_REFDIV_MASK;
+ data = 0x5 << UTMI_PLL_CTRL_REFDIV_OFFSET;
+ /* Feedback Clock Divider Select - 90 for 25Mhz*/
+ mask |= UTMI_PLL_CTRL_FBDIV_MASK;
+ data |= 0x60 << UTMI_PLL_CTRL_FBDIV_OFFSET;
+ /* Select LPFR - 0x0 for 25Mhz/5=5Mhz*/
+ mask |= UTMI_PLL_CTRL_SEL_LPFR_MASK;
+ data |= 0x0 << UTMI_PLL_CTRL_SEL_LPFR_OFFSET;
+ reg_set(utmi_base_addr + UTMI_PLL_CTRL_REG, data, mask);
+
+ /* Impedance Calibration Threshold Setting */
+ reg_set(utmi_base_addr + UTMI_CALIB_CTRL_REG,
+ 0x6 << UTMI_CALIB_CTRL_IMPCAL_VTH_OFFSET,
+ UTMI_CALIB_CTRL_IMPCAL_VTH_MASK);
+
+ /* Set LS TX driver strength coarse control */
+ mask = UTMI_TX_CH_CTRL_DRV_EN_LS_MASK;
+ data = 0x3 << UTMI_TX_CH_CTRL_DRV_EN_LS_OFFSET;
+ /* Set LS TX driver fine adjustment */
+ mask |= UTMI_TX_CH_CTRL_IMP_SEL_LS_MASK;
+ data |= 0x3 << UTMI_TX_CH_CTRL_IMP_SEL_LS_OFFSET;
+ reg_set(utmi_base_addr + UTMI_TX_CH_CTRL_REG, data, mask);
+
+ /* Enable SQ */
+ mask = UTMI_RX_CH_CTRL0_SQ_DET_MASK;
+ data = 0x0 << UTMI_RX_CH_CTRL0_SQ_DET_OFFSET;
+ /* Enable analog squelch detect */
+ mask |= UTMI_RX_CH_CTRL0_SQ_ANA_DTC_MASK;
+ data |= 0x1 << UTMI_RX_CH_CTRL0_SQ_ANA_DTC_OFFSET;
+ reg_set(utmi_base_addr + UTMI_RX_CH_CTRL0_REG, data, mask);
+
+ /* Set External squelch calibration number */
+ mask = UTMI_RX_CH_CTRL1_SQ_AMP_CAL_MASK;
+ data = 0x1 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_OFFSET;
+ /* Enable the External squelch calibration */
+ mask |= UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_MASK;
+ data |= 0x1 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_OFFSET;
+ reg_set(utmi_base_addr + UTMI_RX_CH_CTRL1_REG, data, mask);
+
+ /* Set Control VDAT Reference Voltage - 0.325V */
+ mask = UTMI_CHGDTC_CTRL_VDAT_MASK;
+ data = 0x1 << UTMI_CHGDTC_CTRL_VDAT_OFFSET;
+ /* Set Control VSRC Reference Voltage - 0.6V */
+ mask |= UTMI_CHGDTC_CTRL_VSRC_MASK;
+ data |= 0x1 << UTMI_CHGDTC_CTRL_VSRC_OFFSET;
+ reg_set(utmi_base_addr + UTMI_CHGDTC_CTRL_REG, data, mask);
+
+ debug_exit();
+ return;
+}
+
+static int comphy_utmi_power_up(u32 utmi_index, void __iomem *utmi_base_addr,
+ void __iomem *usb_cfg_addr,
+ void __iomem *utmi_cfg_addr, u32 utmi_phy_port)
+{
+ u32 data, mask, ret = 1;
+ void __iomem *addr;
+
+ debug_enter();
+ debug("stage: UTMI %d - Power up transceiver(Power up Phy), and exit SuspendDM\n",
+ utmi_index);
+ /* Power UP UTMI PHY */
+ reg_set(utmi_cfg_addr, 0x1 << UTMI_PHY_CFG_PU_OFFSET,
+ UTMI_PHY_CFG_PU_MASK);
+ /* Disable Test UTMI select */
+ reg_set(utmi_base_addr + UTMI_CTRL_STATUS0_REG,
+ 0x0 << UTMI_CTRL_STATUS0_TEST_SEL_OFFSET,
+ UTMI_CTRL_STATUS0_TEST_SEL_MASK);
+
+ debug("stage: Polling for PLL and impedance calibration done, and PLL ready done\n");
+ addr = utmi_base_addr + UTMI_CALIB_CTRL_REG;
+ data = UTMI_CALIB_CTRL_IMPCAL_DONE_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 100);
+ if (data != 0) {
+ error("Impedance calibration is not done\n");
+ debug("Read from reg = %p - value = 0x%x\n", addr, data);
+ ret = 0;
+ }
+
+ data = UTMI_CALIB_CTRL_PLLCAL_DONE_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 100);
+ if (data != 0) {
+ error("PLL calibration is not done\n");
+ debug("Read from reg = %p - value = 0x%x\n", addr, data);
+ ret = 0;
+ }
+
+ addr = utmi_base_addr + UTMI_PLL_CTRL_REG;
+ data = UTMI_PLL_CTRL_PLL_RDY_MASK;
+ mask = data;
+ data = polling_with_timeout(addr, data, mask, 100);
+ if (data != 0) {
+ error("PLL is not ready\n");
+ debug("Read from reg = %p - value = 0x%x\n", addr, data);
+ ret = 0;
+ }
+
+ if (ret)
+ debug("Passed\n");
+ else
+ debug("\n");
+
+ debug_exit();
+ return ret;
+}
+
+/*
+ * comphy_utmi_phy_init initialize the UTMI PHY
+ * the init split in 3 parts:
+ * 1. Power down transceiver and PLL
+ * 2. UTMI PHY configure
+ * 3. Powe up transceiver and PLL
+ * Note: - Power down/up should be once for both UTMI PHYs
+ * - comphy_dedicated_phys_init call this function if at least there is
+ * one UTMI PHY exists in FDT blob. access to cp110_utmi_data[0] is
+ * legal
+ */
+static void comphy_utmi_phy_init(u32 utmi_phy_count,
+ struct utmi_phy_data *cp110_utmi_data)
+{
+ u32 i;
+
+ debug_enter();
+ /* UTMI Power down */
+ for (i = 0; i < utmi_phy_count; i++) {
+ comphy_utmi_power_down(i, cp110_utmi_data[i].utmi_base_addr,
+ cp110_utmi_data[i].usb_cfg_addr,
+ cp110_utmi_data[i].utmi_cfg_addr,
+ cp110_utmi_data[i].utmi_phy_port);
+ }
+ /* PLL Power down */
+ debug("stage: UTMI PHY power down PLL\n");
+ for (i = 0; i < utmi_phy_count; i++) {
+ reg_set(cp110_utmi_data[i].usb_cfg_addr,
+ 0x0 << UTMI_USB_CFG_PLL_OFFSET, UTMI_USB_CFG_PLL_MASK);
+ }
+ /* UTMI configure */
+ for (i = 0; i < utmi_phy_count; i++) {
+ comphy_utmi_phy_config(i, cp110_utmi_data[i].utmi_base_addr,
+ cp110_utmi_data[i].usb_cfg_addr,
+ cp110_utmi_data[i].utmi_cfg_addr,
+ cp110_utmi_data[i].utmi_phy_port);
+ }
+ /* UTMI Power up */
+ for (i = 0; i < utmi_phy_count; i++) {
+ if (!comphy_utmi_power_up(i, cp110_utmi_data[i].utmi_base_addr,
+ cp110_utmi_data[i].usb_cfg_addr,
+ cp110_utmi_data[i].utmi_cfg_addr,
+ cp110_utmi_data[i].utmi_phy_port)) {
+ error("Failed to initialize UTMI PHY %d\n", i);
+ continue;
+ }
+ printf("UTMI PHY %d initialized to ", i);
+ if (cp110_utmi_data[i].utmi_phy_port == UTMI_PHY_TO_USB_DEVICE0)
+ printf("USB Device\n");
+ else
+ printf("USB Host%d\n",
+ cp110_utmi_data[i].utmi_phy_port);
+ }
+ /* PLL Power up */
+ debug("stage: UTMI PHY power up PLL\n");
+ for (i = 0; i < utmi_phy_count; i++) {
+ reg_set(cp110_utmi_data[i].usb_cfg_addr,
+ 0x1 << UTMI_USB_CFG_PLL_OFFSET, UTMI_USB_CFG_PLL_MASK);
+ }
+
+ debug_exit();
+ return;
+}
+
+/*
+ * comphy_dedicated_phys_init initialize the dedicated PHYs
+ * - not muxed SerDes lanes e.g. UTMI PHY
+ */
+void comphy_dedicated_phys_init(void)
+{
+ struct utmi_phy_data cp110_utmi_data[MAX_UTMI_PHY_COUNT];
+ int node;
+ int i;
+
+ debug_enter();
+ debug("Initialize USB UTMI PHYs\n");
+
+ /* Find the UTMI phy node in device tree and go over them */
+ node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
+ "marvell,mvebu-utmi-2.6.0");
+
+ i = 0;
+ while (node > 0) {
+ /* get base address of UTMI phy */
+ cp110_utmi_data[i].utmi_base_addr =
+ (void __iomem *)fdtdec_get_addr_size_auto_noparent(
+ gd->fdt_blob, node, "reg", 0, NULL, true);
+ if (cp110_utmi_data[i].utmi_base_addr == NULL) {
+ error("UTMI PHY base address is invalid\n");
+ i++;
+ continue;
+ }
+
+ /* get usb config address */
+ cp110_utmi_data[i].usb_cfg_addr =
+ (void __iomem *)fdtdec_get_addr_size_auto_noparent(
+ gd->fdt_blob, node, "reg", 1, NULL, true);
+ if (cp110_utmi_data[i].usb_cfg_addr == NULL) {
+ error("UTMI PHY base address is invalid\n");
+ i++;
+ continue;
+ }
+
+ /* get UTMI config address */
+ cp110_utmi_data[i].utmi_cfg_addr =
+ (void __iomem *)fdtdec_get_addr_size_auto_noparent(
+ gd->fdt_blob, node, "reg", 2, NULL, true);
+ if (cp110_utmi_data[i].utmi_cfg_addr == NULL) {
+ error("UTMI PHY base address is invalid\n");
+ i++;
+ continue;
+ }
+
+ /*
+ * get the port number (to check if the utmi connected to
+ * host/device)
+ */
+ cp110_utmi_data[i].utmi_phy_port = fdtdec_get_int(
+ gd->fdt_blob, node, "utmi-port", UTMI_PHY_INVALID);
+ if (cp110_utmi_data[i].utmi_phy_port == UTMI_PHY_INVALID) {
+ error("UTMI PHY port type is invalid\n");
+ i++;
+ continue;
+ }
+
+ node = fdt_node_offset_by_compatible(
+ gd->fdt_blob, node, "marvell,mvebu-utmi-2.6.0");
+ i++;
+ }
+
+ if (i > 0)
+ comphy_utmi_phy_init(i, cp110_utmi_data);
+
+ debug_exit();
+}
+
+static void comphy_mux_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *serdes_map)
+{
+ void __iomem *comphy_base_addr;
+ struct comphy_map comphy_map_pipe_data[MAX_LANE_OPTIONS];
+ struct comphy_map comphy_map_phy_data[MAX_LANE_OPTIONS];
+ u32 lane, comphy_max_count;
+
+ comphy_max_count = ptr_chip_cfg->comphy_lanes_count;
+ comphy_base_addr = ptr_chip_cfg->comphy_base_addr;
+
+ /*
+ * Copy the SerDes map configuration for PIPE map and PHY map
+ * the comphy_mux_init modify the type of the lane if the type
+ * is not valid because we have 2 selectores run the
+ * comphy_mux_init twice and after that update the original
+ * serdes_map
+ */
+ for (lane = 0; lane < comphy_max_count; lane++) {
+ comphy_map_pipe_data[lane].type = serdes_map[lane].type;
+ comphy_map_pipe_data[lane].speed = serdes_map[lane].speed;
+ comphy_map_phy_data[lane].type = serdes_map[lane].type;
+ comphy_map_phy_data[lane].speed = serdes_map[lane].speed;
+ }
+ ptr_chip_cfg->mux_data = cp110_comphy_phy_mux_data;
+ comphy_mux_init(ptr_chip_cfg, comphy_map_phy_data,
+ comphy_base_addr + COMMON_SELECTOR_PHY_OFFSET);
+
+ ptr_chip_cfg->mux_data = cp110_comphy_pipe_mux_data;
+ comphy_mux_init(ptr_chip_cfg, comphy_map_pipe_data,
+ comphy_base_addr + COMMON_SELECTOR_PIPE_OFFSET);
+ /* Fix the type after check the PHY and PIPE configuration */
+ for (lane = 0; lane < comphy_max_count; lane++) {
+ if ((comphy_map_pipe_data[lane].type == PHY_TYPE_UNCONNECTED) &&
+ (comphy_map_phy_data[lane].type == PHY_TYPE_UNCONNECTED))
+ serdes_map[lane].type = PHY_TYPE_UNCONNECTED;
+ }
+}
+
+int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+ struct comphy_map *serdes_map)
+{
+ struct comphy_map *ptr_comphy_map;
+ void __iomem *comphy_base_addr, *hpipe_base_addr;
+ u32 comphy_max_count, lane, ret = 0;
+ u32 pcie_width = 0;
+
+ debug_enter();
+
+ comphy_max_count = ptr_chip_cfg->comphy_lanes_count;
+ comphy_base_addr = ptr_chip_cfg->comphy_base_addr;
+ hpipe_base_addr = ptr_chip_cfg->hpipe3_base_addr;
+
+ /* Config Comphy mux configuration */
+ comphy_mux_cp110_init(ptr_chip_cfg, serdes_map);
+
+ /* Check if the first 4 lanes configured as By-4 */
+ for (lane = 0, ptr_comphy_map = serdes_map; lane < 4;
+ lane++, ptr_comphy_map++) {
+ if (ptr_comphy_map->type != PHY_TYPE_PEX0)
+ break;
+ pcie_width++;
+ }
+
+ for (lane = 0, ptr_comphy_map = serdes_map; lane < comphy_max_count;
+ lane++, ptr_comphy_map++) {
+ debug("Initialize serdes number %d\n", lane);
+ debug("Serdes type = 0x%x\n", ptr_comphy_map->type);
+ if (lane == 4) {
+ /*
+ * PCIe lanes above the first 4 lanes, can be only
+ * by1
+ */
+ pcie_width = 1;
+ }
+ switch (ptr_comphy_map->type) {
+ case PHY_TYPE_UNCONNECTED:
+ continue;
+ break;
+ case PHY_TYPE_PEX0:
+ case PHY_TYPE_PEX1:
+ case PHY_TYPE_PEX2:
+ case PHY_TYPE_PEX3:
+ ret = comphy_pcie_power_up(
+ lane, pcie_width, ptr_comphy_map->clk_src,
+ hpipe_base_addr, comphy_base_addr);
+ break;
+ case PHY_TYPE_SATA0:
+ case PHY_TYPE_SATA1:
+ case PHY_TYPE_SATA2:
+ case PHY_TYPE_SATA3:
+ ret = comphy_sata_power_up(
+ lane, hpipe_base_addr, comphy_base_addr,
+ ptr_chip_cfg->comphy_index);
+ break;
+ case PHY_TYPE_USB3_HOST0:
+ case PHY_TYPE_USB3_HOST1:
+ case PHY_TYPE_USB3_DEVICE:
+ ret = comphy_usb3_power_up(lane, hpipe_base_addr,
+ comphy_base_addr);
+ break;
+ case PHY_TYPE_SGMII0:
+ case PHY_TYPE_SGMII1:
+ case PHY_TYPE_SGMII2:
+ case PHY_TYPE_SGMII3:
+ if (ptr_comphy_map->speed == PHY_SPEED_INVALID) {
+ debug("Warning: SGMII PHY speed in lane %d is invalid, set PHY speed to 1.25G\n",
+ lane);
+ ptr_comphy_map->speed = PHY_SPEED_1_25G;
+ }
+ ret = comphy_sgmii_power_up(
+ lane, ptr_comphy_map->speed, hpipe_base_addr,
+ comphy_base_addr);
+ break;
+ case PHY_TYPE_KR:
+ ret = comphy_kr_power_up(lane, hpipe_base_addr,
+ comphy_base_addr);
+ break;
+ case PHY_TYPE_RXAUI0:
+ case PHY_TYPE_RXAUI1:
+ ret = comphy_rxauii_power_up(lane, hpipe_base_addr,
+ comphy_base_addr);
+ break;
+ default:
+ debug("Unknown SerDes type, skip initialize SerDes %d\n",
+ lane);
+ break;
+ }
+ if (ret == 0) {
+ /*
+ * If interface wans't initialiuzed, set the lane to
+ * PHY_TYPE_UNCONNECTED state.
+ */
+ ptr_comphy_map->type = PHY_TYPE_UNCONNECTED;
+ error("PLL is not locked - Failed to initialize lane %d\n",
+ lane);
+ }
+ }
+
+ debug_exit();
+ return 0;
+}
diff --git a/drivers/phy/marvell/comphy_hpipe.h b/drivers/phy/marvell/comphy_hpipe.h
new file mode 100644
index 0000000000..179e910a0c
--- /dev/null
+++ b/drivers/phy/marvell/comphy_hpipe.h
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _COMPHY_HPIPE_H_
+#define _COMPHY_HPIPE_H_
+
+/* SerDes IP register */
+#define SD_EXTERNAL_CONFIG0_REG 0
+#define SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET 1
+#define SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK \
+ (1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET)
+#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET 3
+#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK \
+ (0xf << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET)
+#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET 7
+#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK \
+ (0xf << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET)
+#define SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET 11
+#define SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK \
+ (1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET)
+#define SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET 12
+#define SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK \
+ (1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET)
+#define SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET 14
+#define SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK \
+ (1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET)
+#define SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET 15
+#define SD_EXTERNAL_CONFIG0_MEDIA_MODE_MASK \
+ (0x1 << SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET)
+
+#define SD_EXTERNAL_CONFIG1_REG 0x4
+#define SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET 3
+#define SD_EXTERNAL_CONFIG1_RESET_IN_MASK \
+ (0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET)
+#define SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET 4
+#define SD_EXTERNAL_CONFIG1_RX_INIT_MASK \
+ (0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET)
+#define SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET 5
+#define SD_EXTERNAL_CONFIG1_RESET_CORE_MASK \
+ (0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET)
+#define SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET 6
+#define SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK \
+ (0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET)
+
+#define SD_EXTERNAL_CONFIG2_REG 0x8
+#define SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET 4
+#define SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK \
+ (0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET)
+
+#define SD_EXTERNAL_STATUS0_REG 0x18
+#define SD_EXTERNAL_STATUS0_PLL_TX_OFFSET 2
+#define SD_EXTERNAL_STATUS0_PLL_TX_MASK \
+ (0x1 << SD_EXTERNAL_STATUS0_PLL_TX_OFFSET)
+#define SD_EXTERNAL_STATUS0_PLL_RX_OFFSET 3
+#define SD_EXTERNAL_STATUS0_PLL_RX_MASK \
+ (0x1 << SD_EXTERNAL_STATUS0_PLL_RX_OFFSET)
+#define SD_EXTERNAL_STATUS0_RX_INIT_OFFSET 4
+#define SD_EXTERNAL_STATUS0_RX_INIT_MASK \
+ (0x1 << SD_EXTERNAL_STATUS0_RX_INIT_OFFSET)
+#define SD_EXTERNAL_STATUS0_RF_RESET_IN_OFFSET 6
+#define SD_EXTERNAL_STATUS0_RF_RESET_IN_MASK \
+ (0x1 << SD_EXTERNAL_STATUS0_RF_RESET_IN_OFFSET)
+
+/* HPIPE register */
+#define HPIPE_PWR_PLL_REG 0x4
+#define HPIPE_PWR_PLL_REF_FREQ_OFFSET 0
+#define HPIPE_PWR_PLL_REF_FREQ_MASK \
+ (0x1f << HPIPE_PWR_PLL_REF_FREQ_OFFSET)
+#define HPIPE_PWR_PLL_PHY_MODE_OFFSET 5
+#define HPIPE_PWR_PLL_PHY_MODE_MASK \
+ (0x7 << HPIPE_PWR_PLL_PHY_MODE_OFFSET)
+
+#define HPIPE_KVCO_CALIB_CTRL_REG 0x8
+#define HPIPE_KVCO_CALIB_CTRL_MAX_PLL_OFFSET 12
+#define HPIPE_KVCO_CALIB_CTRL_MAX_PLL_MASK \
+ (0x1 << HPIPE_KVCO_CALIB_CTRL_MAX_PLL_OFFSET)
+
+#define HPIPE_CAL_REG1_REG 0xc
+#define HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET 10
+#define HPIPE_CAL_REG_1_EXT_TXIMP_MASK \
+ (0x1f << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET)
+#define HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET 15
+#define HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK \
+ (0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET)
+
+#define HPIPE_SQUELCH_FFE_SETTING_REG 0x018
+
+#define HPIPE_DFE_REG0 0x01C
+#define HPIPE_DFE_RES_FORCE_OFFSET 15
+#define HPIPE_DFE_RES_FORCE_MASK \
+ (0x1 << HPIPE_DFE_RES_FORCE_OFFSET)
+
+#define HPIPE_DFE_F3_F5_REG 0x028
+#define HPIPE_DFE_F3_F5_DFE_EN_OFFSET 14
+#define HPIPE_DFE_F3_F5_DFE_EN_MASK \
+ (0x1 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET)
+#define HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET 15
+#define HPIPE_DFE_F3_F5_DFE_CTRL_MASK \
+ (0x1 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET)
+
+#define HPIPE_G1_SET_0_REG 0x034
+#define HPIPE_G1_SET_0_G1_TX_AMP_OFFSET 1
+#define HPIPE_G1_SET_0_G1_TX_AMP_MASK \
+ (0x1f << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET)
+#define HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET 7
+#define HPIPE_G1_SET_0_G1_TX_EMPH1_MASK \
+ (0xf << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET)
+
+#define HPIPE_G1_SET_1_REG 0x038
+#define HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET 0
+#define HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK \
+ (0x7 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET)
+#define HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET 3
+#define HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK \
+ (0x7 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET)
+#define HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET 10
+#define HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK \
+ (0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET)
+
+#define HPIPE_G2_SETTINGS_1_REG 0x040
+
+#define HPIPE_G3_SETTINGS_1_REG 0x048
+#define HPIPE_G3_RX_SELMUPI_OFFSET 0
+#define HPIPE_G3_RX_SELMUPI_MASK \
+ (0x7 << HPIPE_G3_RX_SELMUPI_OFFSET)
+#define HPIPE_G3_RX_SELMUPF_OFFSET 3
+#define HPIPE_G3_RX_SELMUPF_MASK \
+ (0x7 << HPIPE_G3_RX_SELMUPF_OFFSET)
+#define HPIPE_G3_SETTING_BIT_OFFSET 13
+#define HPIPE_G3_SETTING_BIT_MASK \
+ (0x1 << HPIPE_G3_SETTING_BIT_OFFSET)
+
+#define HPIPE_LOOPBACK_REG 0x08c
+#define HPIPE_LOOPBACK_SEL_OFFSET 1
+#define HPIPE_LOOPBACK_SEL_MASK \
+ (0x7 << HPIPE_LOOPBACK_SEL_OFFSET)
+
+#define HPIPE_SYNC_PATTERN_REG 0x090
+
+#define HPIPE_INTERFACE_REG 0x94
+#define HPIPE_INTERFACE_GEN_MAX_OFFSET 10
+#define HPIPE_INTERFACE_GEN_MAX_MASK \
+ (0x3 << HPIPE_INTERFACE_GEN_MAX_OFFSET)
+#define HPIPE_INTERFACE_LINK_TRAIN_OFFSET 14
+#define HPIPE_INTERFACE_LINK_TRAIN_MASK \
+ (0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET)
+
+#define HPIPE_ISOLATE_MODE_REG 0x98
+#define HPIPE_ISOLATE_MODE_GEN_RX_OFFSET 0
+#define HPIPE_ISOLATE_MODE_GEN_RX_MASK \
+ (0xf << HPIPE_ISOLATE_MODE_GEN_RX_OFFSET)
+#define HPIPE_ISOLATE_MODE_GEN_TX_OFFSET 4
+#define HPIPE_ISOLATE_MODE_GEN_TX_MASK \
+ (0xf << HPIPE_ISOLATE_MODE_GEN_TX_OFFSET)
+
+#define HPIPE_G1_SET_2_REG 0xf4
+#define HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET 0
+#define HPIPE_G1_SET_2_G1_TX_EMPH0_MASK \
+ (0xf << HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET)
+#define HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET 4
+#define HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK \
+ (0x1 << HPIPE_G1_SET_2_G1_TX_EMPH0_MASK)
+
+#define HPIPE_VTHIMPCAL_CTRL_REG 0x104
+
+#define HPIPE_PCIE_REG0 0x120
+#define HPIPE_PCIE_IDLE_SYNC_OFFSET 12
+#define HPIPE_PCIE_IDLE_SYNC_MASK \
+ (0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET)
+#define HPIPE_PCIE_SEL_BITS_OFFSET 13
+#define HPIPE_PCIE_SEL_BITS_MASK \
+ (0x3 << HPIPE_PCIE_SEL_BITS_OFFSET)
+
+#define HPIPE_LANE_ALIGN_REG 0x124
+#define HPIPE_LANE_ALIGN_OFF_OFFSET 12
+#define HPIPE_LANE_ALIGN_OFF_MASK \
+ (0x1 << HPIPE_LANE_ALIGN_OFF_OFFSET)
+
+#define HPIPE_MISC_REG 0x13C
+#define HPIPE_MISC_CLK100M_125M_OFFSET 4
+#define HPIPE_MISC_CLK100M_125M_MASK \
+ (0x1 << HPIPE_MISC_CLK100M_125M_OFFSET)
+#define HPIPE_MISC_ICP_FORCE_OFFSET 5
+#define HPIPE_MISC_ICP_FORCE_MASK \
+ (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET)
+#define HPIPE_MISC_TXDCLK_2X_OFFSET 6
+#define HPIPE_MISC_TXDCLK_2X_MASK \
+ (0x1 << HPIPE_MISC_TXDCLK_2X_OFFSET)
+#define HPIPE_MISC_CLK500_EN_OFFSET 7
+#define HPIPE_MISC_CLK500_EN_MASK \
+ (0x1 << HPIPE_MISC_CLK500_EN_OFFSET)
+#define HPIPE_MISC_REFCLK_SEL_OFFSET 10
+#define HPIPE_MISC_REFCLK_SEL_MASK \
+ (0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET)
+
+#define HPIPE_RX_CONTROL_1_REG 0x140
+#define HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET 11
+#define HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK \
+ (0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET)
+#define HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET 12
+#define HPIPE_RX_CONTROL_1_CLK8T_EN_MASK \
+ (0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET)
+
+#define HPIPE_PWR_CTR_REG 0x148
+#define HPIPE_PWR_CTR_RST_DFE_OFFSET 0
+#define HPIPE_PWR_CTR_RST_DFE_MASK \
+ (0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET)
+#define HPIPE_PWR_CTR_SFT_RST_OFFSET 10
+#define HPIPE_PWR_CTR_SFT_RST_MASK \
+ (0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET)
+
+#define HPIPE_PLLINTP_REG1 0x150
+
+#define HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG 0x16C
+#define HPIPE_SMAPLER_OFFSET 12
+#define HPIPE_SMAPLER_MASK \
+ (0x1 << HPIPE_SMAPLER_OFFSET)
+
+#define HPIPE_TX_REG1_REG 0x174
+#define HPIPE_TX_REG1_TX_EMPH_RES_OFFSET 5
+#define HPIPE_TX_REG1_TX_EMPH_RES_MASK \
+ (0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET)
+#define HPIPE_TX_REG1_SLC_EN_OFFSET 10
+#define HPIPE_TX_REG1_SLC_EN_MASK \
+ (0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET)
+
+#define HPIPE_PWR_CTR_DTL_REG 0x184
+#define HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET 2
+#define HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK \
+ (0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET)
+
+#define HPIPE_RX_REG3 0x188
+
+#define HPIPE_TX_TRAIN_CTRL_0_REG 0x268
+#define HPIPE_TX_TRAIN_P2P_HOLD_OFFSET 15
+#define HPIPE_TX_TRAIN_P2P_HOLD_MASK \
+ (0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET)
+
+#define HPIPE_TX_TRAIN_CTRL_REG 0x26C
+#define HPIPE_TX_TRAIN_CTRL_G1_OFFSET 0
+#define HPIPE_TX_TRAIN_CTRL_G1_MASK \
+ (0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET)
+#define HPIPE_TX_TRAIN_CTRL_GN1_OFFSET 1
+#define HPIPE_TX_TRAIN_CTRL_GN1_MASK \
+ (0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET)
+#define HPIPE_TX_TRAIN_CTRL_G0_OFFSET 2
+#define HPIPE_TX_TRAIN_CTRL_G0_MASK \
+ (0x1 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET)
+
+#define HPIPE_TX_TRAIN_CTRL_4_REG 0x278
+#define HPIPE_TRX_TRAIN_TIMER_OFFSET 0
+#define HPIPE_TRX_TRAIN_TIMER_MASK \
+ (0x3FF << HPIPE_TRX_TRAIN_TIMER_OFFSET)
+
+#define HPIPE_PCIE_REG1 0x288
+#define HPIPE_PCIE_REG3 0x290
+
+#define HPIPE_TX_TRAIN_CTRL_5_REG 0x2A4
+#define HPIPE_TX_TRAIN_START_SQ_EN_OFFSET 11
+#define HPIPE_TX_TRAIN_START_SQ_EN_MASK \
+ (0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET)
+#define HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET 12
+#define HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK \
+ (0x1 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET)
+#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET 13
+#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK \
+ (0x1 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET)
+#define HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET 14
+#define HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK \
+ (0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET)
+
+#define HPIPE_TX_TRAIN_REG 0x31C
+#define HPIPE_TX_TRAIN_CHK_INIT_OFFSET 4
+#define HPIPE_TX_TRAIN_CHK_INIT_MASK \
+ (0x1 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET)
+#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET 7
+#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK \
+ (0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET)
+
+#define HPIPE_TX_TRAIN_CTRL_11_REG 0x438
+#define HPIPE_TX_STATUS_CHECK_MODE_OFFSET 6
+#define HPIPE_TX_TX_STATUS_CHECK_MODE_MASK \
+ (0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET)
+#define HPIPE_TX_NUM_OF_PRESET_OFFSET 10
+#define HPIPE_TX_NUM_OF_PRESET_MASK \
+ (0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET)
+#define HPIPE_TX_SWEEP_PRESET_EN_OFFSET 15
+#define HPIPE_TX_SWEEP_PRESET_EN_MASK \
+ (0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET)
+
+#define HPIPE_G1_SETTINGS_3_REG 0x440
+#define HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET 9
+#define HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK \
+ (0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET)
+
+#define HPIPE_G1_SETTINGS_4_REG 0x444
+#define HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET 8
+#define HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK \
+ (0x3 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET)
+
+#define HPIPE_G2_SETTINGS_3_REG 0x448
+#define HPIPE_G2_SETTINGS_4_REG 0x44C
+
+#define HPIPE_G3_SETTING_3_REG 0x450
+#define HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET 12
+#define HPIPE_G3_FFE_DEG_RES_LEVEL_MASK \
+ (0x3 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET)
+#define HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET 14
+#define HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK \
+ (0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET)
+
+#define HPIPE_G3_SETTING_4_REG 0x454
+#define HPIPE_G3_DFE_RES_OFFSET 8
+#define HPIPE_G3_DFE_RES_MASK \
+ (0x3 << HPIPE_G3_DFE_RES_OFFSET)
+
+#define HPIPE_DFE_CTRL_28_REG 0x49C
+#define HPIPE_DFE_CTRL_28_PIPE4_OFFSET 7
+#define HPIPE_DFE_CTRL_28_PIPE4_MASK \
+ (0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET)
+
+#define HPIPE_G1_SETTING_5_REG 0x538
+#define HPIPE_G1_SETTING_5_G1_ICP_OFFSET 0
+#define HPIPE_G1_SETTING_5_G1_ICP_MASK \
+ (0xf << HPIPE_G1_SETTING_5_G1_ICP_OFFSET)
+
+#define HPIPE_LANE_CONFIG0_REG 0x600
+#define HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET 0
+#define HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK \
+ (0x1 << HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET)
+
+#define HPIPE_LANE_CONFIG1_REG 0x604
+#define HPIPE_LANE_CONFIG1_MAX_PLL_OFFSET 9
+#define HPIPE_LANE_CONFIG1_MAX_PLL_MASK \
+ (0x1 << HPIPE_LANE_CONFIG1_MAX_PLL_OFFSET)
+#define HPIPE_LANE_CONFIG1_GEN2_PLL_OFFSET 10
+#define HPIPE_LANE_CONFIG1_GEN2_PLL_MASK \
+ (0x1 << HPIPE_LANE_CONFIG1_GEN2_PLL_OFFSET)
+
+#define HPIPE_LANE_STATUS1_REG 0x60C
+#define HPIPE_LANE_STATUS1_PCLK_EN_OFFSET 0
+#define HPIPE_LANE_STATUS1_PCLK_EN_MASK \
+ (0x1 << HPIPE_LANE_STATUS1_PCLK_EN_OFFSET)
+
+#define HPIPE_LANE_CFG4_REG 0x620
+#define HPIPE_LANE_CFG4_DFE_CTRL_OFFSET 0
+#define HPIPE_LANE_CFG4_DFE_CTRL_MASK \
+ (0x7 << HPIPE_LANE_CFG4_DFE_CTRL_OFFSET)
+#define HPIPE_LANE_CFG4_DFE_OVER_OFFSET 6
+#define HPIPE_LANE_CFG4_DFE_OVER_MASK \
+ (0x1 << HPIPE_LANE_CFG4_DFE_OVER_OFFSET)
+#define HPIPE_LANE_CFG4_SSC_CTRL_OFFSET 7
+#define HPIPE_LANE_CFG4_SSC_CTRL_MASK \
+ (0x1 << HPIPE_LANE_CFG4_SSC_CTRL_OFFSET)
+
+#define HPIPE_LANE_EQU_CONFIG_0_REG 0x69C
+#define HPIPE_CFG_PHY_RC_EP_OFFSET 12
+#define HPIPE_CFG_PHY_RC_EP_MASK \
+ (0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET)
+
+#define HPIPE_LANE_EQ_CFG1_REG 0x6a0
+#define HPIPE_CFG_UPDATE_POLARITY_OFFSET 12
+#define HPIPE_CFG_UPDATE_POLARITY_MASK \
+ (0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET)
+
+#define HPIPE_RST_CLK_CTRL_REG 0x704
+#define HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET 0
+#define HPIPE_RST_CLK_CTRL_PIPE_RST_MASK \
+ (0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET)
+#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET 2
+#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK \
+ (0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET)
+#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET 3
+#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK \
+ (0x1 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET)
+#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET 9
+#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK \
+ (0x1 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET)
+
+#define HPIPE_TST_MODE_CTRL_REG 0x708
+#define HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET 2
+#define HPIPE_TST_MODE_CTRL_MODE_MARGIN_MASK \
+ (0x1 << HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET)
+
+#define HPIPE_CLK_SRC_LO_REG 0x70c
+#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET 1
+#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK \
+ (0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET)
+#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET 2
+#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK \
+ (0x3 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET)
+#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET 5
+#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK \
+ (0x7 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET)
+
+#define HPIPE_CLK_SRC_HI_REG 0x710
+#define HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET 0
+#define HPIPE_CLK_SRC_HI_LANE_STRT_MASK \
+ (0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET)
+#define HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET 1
+#define HPIPE_CLK_SRC_HI_LANE_BREAK_MASK \
+ (0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET)
+#define HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET 2
+#define HPIPE_CLK_SRC_HI_LANE_MASTER_MASK \
+ (0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET)
+#define HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET 7
+#define HPIPE_CLK_SRC_HI_MODE_PIPE_MASK \
+ (0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET)
+
+#define HPIPE_GLOBAL_MISC_CTRL 0x718
+#define HPIPE_GLOBAL_PM_CTRL 0x740
+#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET 0
+#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK \
+ (0xFF << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET)
+
+#endif /* _COMPHY_HPIPE_H_ */
+
diff --git a/drivers/phy/marvell/comphy_mux.c b/drivers/phy/marvell/comphy_mux.c
new file mode 100644
index 0000000000..1dc7426b63
--- /dev/null
+++ b/drivers/phy/marvell/comphy_mux.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#include "comphy.h"
+#include "comphy_hpipe.h"
+
+/*
+ * comphy_mux_check_config()
+ * description: this function passes over the COMPHY lanes and check if the type
+ * is valid for specific lane. If the type is not valid,
+ * the function update the struct and set the type of the lane as
+ * PHY_TYPE_UNCONNECTED
+ */
+static void comphy_mux_check_config(struct comphy_mux_data *mux_data,
+ struct comphy_map *comphy_map_data, int comphy_max_lanes)
+{
+ struct comphy_mux_options *mux_opt;
+ int lane, opt, valid;
+
+ debug_enter();
+
+ for (lane = 0; lane < comphy_max_lanes;
+ lane++, comphy_map_data++, mux_data++) {
+ mux_opt = mux_data->mux_values;
+ for (opt = 0, valid = 0; opt < mux_data->max_lane_values;
+ opt++, mux_opt++) {
+ if (mux_opt->type == comphy_map_data->type) {
+ valid = 1;
+ break;
+ }
+ }
+ if (valid == 0) {
+ debug("lane number %d, had invalid type %d\n",
+ lane, comphy_map_data->type);
+ debug("set lane %d as type %d\n", lane,
+ PHY_TYPE_UNCONNECTED);
+ comphy_map_data->type = PHY_TYPE_UNCONNECTED;
+ } else {
+ debug("lane number %d, has type %d\n",
+ lane, comphy_map_data->type);
+ }
+ }
+
+ debug_exit();
+}
+
+static u32 comphy_mux_get_mux_value(struct comphy_mux_data *mux_data,
+ u32 type, int lane)
+{
+ struct comphy_mux_options *mux_opt;
+ int opt;
+ u32 value = 0;
+
+ debug_enter();
+
+ mux_opt = mux_data->mux_values;
+ for (opt = 0 ; opt < mux_data->max_lane_values; opt++, mux_opt++) {
+ if (mux_opt->type == type) {
+ value = mux_opt->mux_value;
+ break;
+ }
+ }
+
+ debug_exit();
+
+ return value;
+}
+
+static void comphy_mux_reg_write(struct comphy_mux_data *mux_data,
+ struct comphy_map *comphy_map_data,
+ int comphy_max_lanes,
+ void __iomem *selector_base, u32 bitcount)
+{
+ u32 lane, value, offset, mask;
+
+ debug_enter();
+
+ for (lane = 0; lane < comphy_max_lanes;
+ lane++, comphy_map_data++, mux_data++) {
+ offset = lane * bitcount;
+ mask = (((1 << bitcount) - 1) << offset);
+ value = (comphy_mux_get_mux_value(mux_data,
+ comphy_map_data->type,
+ lane) << offset);
+ reg_set(selector_base, value, mask);
+ }
+
+ debug_exit();
+}
+
+void comphy_mux_init(struct chip_serdes_phy_config *chip_cfg,
+ struct comphy_map *comphy_map_data,
+ void __iomem *selector_base)
+{
+ struct comphy_mux_data *mux_data;
+ u32 mux_bitcount;
+ u32 comphy_max_lanes;
+
+ debug_enter();
+
+ comphy_max_lanes = chip_cfg->comphy_lanes_count;
+ mux_data = chip_cfg->mux_data;
+ mux_bitcount = chip_cfg->comphy_mux_bitcount;
+
+ /* check if the configuration is valid */
+ comphy_mux_check_config(mux_data, comphy_map_data, comphy_max_lanes);
+ /* Init COMPHY selectors */
+ comphy_mux_reg_write(mux_data, comphy_map_data, comphy_max_lanes,
+ selector_base, mux_bitcount);
+
+ debug_exit();
+}
diff --git a/drivers/phy/marvell/sata.h b/drivers/phy/marvell/sata.h
new file mode 100644
index 0000000000..be2ba54a0d
--- /dev/null
+++ b/drivers/phy/marvell/sata.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _SATA_H_
+#define _SATA_H_
+
+/* SATA3 Unit address */
+#define SATA3_VENDOR_ADDRESS 0xA0
+#define SATA3_VENDOR_ADDR_OFSSET 0
+#define SATA3_VENDOR_ADDR_MASK (0xFFFFFFFF << SATA3_VENDOR_ADDR_OFSSET)
+#define SATA3_VENDOR_DATA 0xA4
+
+#define SATA_CONTROL_REG 0x0
+#define SATA3_CTRL_SATA0_PD_OFFSET 6
+#define SATA3_CTRL_SATA0_PD_MASK (1 << SATA3_CTRL_SATA0_PD_OFFSET)
+#define SATA3_CTRL_SATA1_PD_OFFSET 14
+#define SATA3_CTRL_SATA1_PD_MASK (1 << SATA3_CTRL_SATA1_PD_OFFSET)
+#define SATA3_CTRL_SATA1_ENABLE_OFFSET 22
+#define SATA3_CTRL_SATA1_ENABLE_MASK (1 << SATA3_CTRL_SATA1_ENABLE_OFFSET)
+#define SATA3_CTRL_SATA_SSU_OFFSET 23
+#define SATA3_CTRL_SATA_SSU_MASK (1 << SATA3_CTRL_SATA_SSU_OFFSET)
+
+#define SATA_MBUS_SIZE_SELECT_REG 0x4
+#define SATA_MBUS_REGRET_EN_OFFSET 7
+#define SATA_MBUS_REGRET_EN_MASK (0x1 << SATA_MBUS_REGRET_EN_OFFSET)
+
+#endif /* _SATA_H_ */
diff --git a/drivers/phy/marvell/utmi_phy.h b/drivers/phy/marvell/utmi_phy.h
new file mode 100644
index 0000000000..01e53ba0fd
--- /dev/null
+++ b/drivers/phy/marvell/utmi_phy.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _UTMI_PHY_H_
+#define _UTMI_PHY_H_
+
+#define UTMI_USB_CFG_DEVICE_EN_OFFSET 0
+#define UTMI_USB_CFG_DEVICE_EN_MASK \
+ (0x1 << UTMI_USB_CFG_DEVICE_EN_OFFSET)
+#define UTMI_USB_CFG_DEVICE_MUX_OFFSET 1
+#define UTMI_USB_CFG_DEVICE_MUX_MASK \
+ (0x1 << UTMI_USB_CFG_DEVICE_MUX_OFFSET)
+#define UTMI_USB_CFG_PLL_OFFSET 25
+#define UTMI_USB_CFG_PLL_MASK \
+ (0x1 << UTMI_USB_CFG_PLL_OFFSET)
+
+#define UTMI_PHY_CFG_PU_OFFSET 5
+#define UTMI_PHY_CFG_PU_MASK \
+ (0x1 << UTMI_PHY_CFG_PU_OFFSET)
+
+#define UTMI_PLL_CTRL_REG 0x0
+#define UTMI_PLL_CTRL_REFDIV_OFFSET 0
+#define UTMI_PLL_CTRL_REFDIV_MASK \
+ (0x7f << UTMI_PLL_CTRL_REFDIV_OFFSET)
+#define UTMI_PLL_CTRL_FBDIV_OFFSET 16
+#define UTMI_PLL_CTRL_FBDIV_MASK \
+ (0x1FF << UTMI_PLL_CTRL_FBDIV_OFFSET)
+#define UTMI_PLL_CTRL_SEL_LPFR_OFFSET 28
+#define UTMI_PLL_CTRL_SEL_LPFR_MASK \
+ (0x3 << UTMI_PLL_CTRL_SEL_LPFR_OFFSET)
+#define UTMI_PLL_CTRL_PLL_RDY_OFFSET 31
+#define UTMI_PLL_CTRL_PLL_RDY_MASK \
+ (0x1 << UTMI_PLL_CTRL_PLL_RDY_OFFSET)
+
+#define UTMI_CALIB_CTRL_REG 0x8
+#define UTMI_CALIB_CTRL_IMPCAL_VTH_OFFSET 8
+#define UTMI_CALIB_CTRL_IMPCAL_VTH_MASK \
+ (0x7 << UTMI_CALIB_CTRL_IMPCAL_VTH_OFFSET)
+#define UTMI_CALIB_CTRL_IMPCAL_DONE_OFFSET 23
+#define UTMI_CALIB_CTRL_IMPCAL_DONE_MASK \
+ (0x1 << UTMI_CALIB_CTRL_IMPCAL_DONE_OFFSET)
+#define UTMI_CALIB_CTRL_PLLCAL_DONE_OFFSET 31
+#define UTMI_CALIB_CTRL_PLLCAL_DONE_MASK \
+ (0x1 << UTMI_CALIB_CTRL_PLLCAL_DONE_OFFSET)
+
+#define UTMI_TX_CH_CTRL_REG 0xC
+#define UTMI_TX_CH_CTRL_DRV_EN_LS_OFFSET 12
+#define UTMI_TX_CH_CTRL_DRV_EN_LS_MASK \
+ (0xf << UTMI_TX_CH_CTRL_DRV_EN_LS_OFFSET)
+#define UTMI_TX_CH_CTRL_IMP_SEL_LS_OFFSET 16
+#define UTMI_TX_CH_CTRL_IMP_SEL_LS_MASK \
+ (0xf << UTMI_TX_CH_CTRL_IMP_SEL_LS_OFFSET)
+
+#define UTMI_RX_CH_CTRL0_REG 0x14
+#define UTMI_RX_CH_CTRL0_SQ_DET_OFFSET 15
+#define UTMI_RX_CH_CTRL0_SQ_DET_MASK \
+ (0x1 << UTMI_RX_CH_CTRL0_SQ_DET_OFFSET)
+#define UTMI_RX_CH_CTRL0_SQ_ANA_DTC_OFFSET 28
+#define UTMI_RX_CH_CTRL0_SQ_ANA_DTC_MASK \
+ (0x1 << UTMI_RX_CH_CTRL0_SQ_ANA_DTC_OFFSET)
+
+#define UTMI_RX_CH_CTRL1_REG 0x18
+#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_OFFSET 0
+#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_MASK \
+ (0x3 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_OFFSET)
+#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_OFFSET 3
+#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_MASK \
+ (0x1 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_OFFSET)
+
+#define UTMI_CTRL_STATUS0_REG 0x24
+#define UTMI_CTRL_STATUS0_SUSPENDM_OFFSET 22
+#define UTMI_CTRL_STATUS0_SUSPENDM_MASK \
+ (0x1 << UTMI_CTRL_STATUS0_SUSPENDM_OFFSET)
+#define UTMI_CTRL_STATUS0_TEST_SEL_OFFSET 25
+#define UTMI_CTRL_STATUS0_TEST_SEL_MASK \
+ (0x1 << UTMI_CTRL_STATUS0_TEST_SEL_OFFSET)
+
+#define UTMI_CHGDTC_CTRL_REG 0x38
+#define UTMI_CHGDTC_CTRL_VDAT_OFFSET 8
+#define UTMI_CHGDTC_CTRL_VDAT_MASK \
+ (0x3 << UTMI_CHGDTC_CTRL_VDAT_OFFSET)
+#define UTMI_CHGDTC_CTRL_VSRC_OFFSET 10
+#define UTMI_CHGDTC_CTRL_VSRC_MASK \
+ (0x3 << UTMI_CHGDTC_CTRL_VSRC_OFFSET)
+
+#endif /* _UTMI_PHY_H_ */
+
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ab5df70bfc..541cf2e512 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -147,6 +147,13 @@ config DEBUG_UART_ARM_DCC
This port is available at least on ARMv6, ARMv7, ARMv8 and XScale
architectures.
+config DEBUG_MVEBU_A3700_UART
+ bool "Marvell Armada 3700"
+ help
+ Select this to enable a debug UART using the serial_mvebu driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver-model serial is running.
+
config DEBUG_UART_ZYNQ
bool "Xilinx Zynq"
help
@@ -295,6 +302,13 @@ config FSL_LPUART
Select this to enable a Low Power UART for Freescale VF610 and
QorIQ Layerscape devices.
+config MVEBU_A3700_UART
+ bool "UART support for Armada 3700"
+ default n
+ help
+ Choose this option to add support for UART driver on the Marvell
+ Armada 3700 SoC. The base address is configured via DT.
+
config PIC32_SERIAL
bool "Support for Microchip PIC32 on-chip UART"
depends on DM_SERIAL && MACH_PIC32
@@ -371,4 +385,5 @@ config MSM_SERIAL
It should support all Qualcomm devices with UARTDM version 1.4,
for example APQ8016 and MSM8916.
Single baudrate is supported in current implementation (115200).
+
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 6986d659ab..21b129206a 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
obj-$(CONFIG_STM32X7_SERIAL) += serial_stm32x7.o
obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o
obj-$(CONFIG_MSM_SERIAL) += serial_msm.o
+obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_USB_TTY) += usbtty.o
diff --git a/drivers/serial/serial_mvebu_a3700.c b/drivers/serial/serial_mvebu_a3700.c
new file mode 100644
index 0000000000..192e79a3d3
--- /dev/null
+++ b/drivers/serial/serial_mvebu_a3700.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <serial.h>
+#include <asm/io.h>
+
+struct mvebu_platdata {
+ void __iomem *base;
+};
+
+/*
+ * Register offset
+ */
+#define UART_RX_REG 0x00
+#define UART_TX_REG 0x04
+#define UART_CTRL_REG 0x08
+#define UART_STATUS_REG 0x0c
+#define UART_BAUD_REG 0x10
+#define UART_POSSR_REG 0x14
+
+#define UART_STATUS_RX_RDY 0x10
+#define UART_STATUS_TXFIFO_FULL 0x800
+
+#define UART_CTRL_RXFIFO_RESET 0x4000
+#define UART_CTRL_TXFIFO_RESET 0x8000
+
+#define CONFIG_UART_BASE_CLOCK 25804800
+
+static int mvebu_serial_putc(struct udevice *dev, const char ch)
+{
+ struct mvebu_platdata *plat = dev_get_platdata(dev);
+ void __iomem *base = plat->base;
+
+ while (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL)
+ ;
+
+ writel(ch, base + UART_TX_REG);
+
+ return 0;
+}
+
+static int mvebu_serial_getc(struct udevice *dev)
+{
+ struct mvebu_platdata *plat = dev_get_platdata(dev);
+ void __iomem *base = plat->base;
+
+ while (!(readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY))
+ ;
+
+ return readl(base + UART_RX_REG) & 0xff;
+}
+
+static int mvebu_serial_pending(struct udevice *dev, bool input)
+{
+ struct mvebu_platdata *plat = dev_get_platdata(dev);
+ void __iomem *base = plat->base;
+
+ if (readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY)
+ return 1;
+
+ return 0;
+}
+
+static int mvebu_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct mvebu_platdata *plat = dev_get_platdata(dev);
+ void __iomem *base = plat->base;
+
+ /*
+ * Calculate divider
+ * baudrate = clock / 16 / divider
+ */
+ writel(CONFIG_UART_BASE_CLOCK / baudrate / 16, base + UART_BAUD_REG);
+
+ /*
+ * Set Programmable Oversampling Stack to 0,
+ * UART defaults to 16x scheme
+ */
+ writel(0, base + UART_POSSR_REG);
+
+ return 0;
+}
+
+static int mvebu_serial_probe(struct udevice *dev)
+{
+ struct mvebu_platdata *plat = dev_get_platdata(dev);
+ void __iomem *base = plat->base;
+
+ /* reset FIFOs */
+ writel(UART_CTRL_RXFIFO_RESET | UART_CTRL_TXFIFO_RESET,
+ base + UART_CTRL_REG);
+
+ /* No Parity, 1 Stop */
+ writel(0, base + UART_CTRL_REG);
+
+ return 0;
+}
+
+static int mvebu_serial_ofdata_to_platdata(struct udevice *dev)
+{
+ struct mvebu_platdata *plat = dev_get_platdata(dev);
+
+ plat->base = dev_get_addr_ptr(dev);
+
+ return 0;
+}
+
+static const struct dm_serial_ops mvebu_serial_ops = {
+ .putc = mvebu_serial_putc,
+ .pending = mvebu_serial_pending,
+ .getc = mvebu_serial_getc,
+ .setbrg = mvebu_serial_setbrg,
+};
+
+static const struct udevice_id mvebu_serial_ids[] = {
+ { .compatible = "marvell,armada-3700-uart" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_mvebu) = {
+ .name = "serial_mvebu",
+ .id = UCLASS_SERIAL,
+ .of_match = mvebu_serial_ids,
+ .ofdata_to_platdata = mvebu_serial_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct mvebu_platdata),
+ .probe = mvebu_serial_probe,
+ .ops = &mvebu_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+#ifdef CONFIG_DEBUG_MVEBU_A3700_UART
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
+
+ /* reset FIFOs */
+ writel(UART_CTRL_RXFIFO_RESET | UART_CTRL_TXFIFO_RESET,
+ base + UART_CTRL_REG);
+
+ /* No Parity, 1 Stop */
+ writel(0, base + UART_CTRL_REG);
+
+ /*
+ * Calculate divider
+ * baudrate = clock / 16 / divider
+ */
+ writel(CONFIG_UART_BASE_CLOCK / 115200 / 16, base + UART_BAUD_REG);
+
+ /*
+ * Set Programmable Oversampling Stack to 0,
+ * UART defaults to 16x scheme
+ */
+ writel(0, base + UART_POSSR_REG);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
+
+ while (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL)
+ ;
+
+ writel(ch, base + UART_TX_REG);
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 5da66a6de0..8724f87c49 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -68,6 +68,13 @@ config ICH_SPI
access the SPI NOR flash on platforms embedding this Intel
ICH IP core.
+config MVEBU_A3700_SPI
+ bool "Marvell Armada 3700 SPI driver"
+ help
+ Enable the Marvell Armada 3700 SPI driver. This driver can be
+ used to access the SPI NOR flash on platforms embedding this
+ Marvell IP core.
+
config PIC32_SPI
bool "Microchip PIC32 SPI driver"
depends on MACH_PIC32
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index b1d9e2075e..247c5f6558 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
+obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
obj-$(CONFIG_MXC_SPI) += mxc_spi.o
obj-$(CONFIG_MXS_SPI) += mxs_spi.o
obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
new file mode 100644
index 0000000000..7c58c3661f
--- /dev/null
+++ b/drivers/spi/mvebu_a3700_spi.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2015 Marvell International Ltd.
+ *
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <spi.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define MVEBU_SPI_A3700_XFER_RDY BIT(1)
+#define MVEBU_SPI_A3700_FIFO_FLUSH BIT(9)
+#define MVEBU_SPI_A3700_BYTE_LEN BIT(5)
+#define MVEBU_SPI_A3700_CLK_PHA BIT(6)
+#define MVEBU_SPI_A3700_CLK_POL BIT(7)
+#define MVEBU_SPI_A3700_FIFO_EN BIT(17)
+#define MVEBU_SPI_A3700_SPI_EN_0 BIT(16)
+#define MVEBU_SPI_A3700_CLK_PRESCALE_BIT 0
+#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK \
+ (0x1f << MVEBU_SPI_A3700_CLK_PRESCALE_BIT)
+
+/* SPI registers */
+struct spi_reg {
+ u32 ctrl; /* 0x10600 */
+ u32 cfg; /* 0x10604 */
+ u32 dout; /* 0x10608 */
+ u32 din; /* 0x1060c */
+};
+
+struct mvebu_spi_platdata {
+ struct spi_reg *spireg;
+ unsigned int frequency;
+ unsigned int clock;
+};
+
+static void spi_cs_activate(struct spi_reg *reg, int cs)
+{
+ setbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
+}
+
+static void spi_cs_deactivate(struct spi_reg *reg, int cs)
+{
+ clrbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
+}
+
+/**
+ * spi_legacy_shift_byte() - triggers the real SPI transfer
+ * @bytelen: Indicate how many bytes to transfer.
+ * @dout: Buffer address of what to send.
+ * @din: Buffer address of where to receive.
+ *
+ * This function triggers the real SPI transfer in legacy mode. It
+ * will shift out char buffer from @dout, and shift in char buffer to
+ * @din, if necessary.
+ *
+ * This function assumes that only one byte is shifted at one time.
+ * However, it is not its responisbility to set the transfer type to
+ * one-byte. Also, it does not guarantee that it will work if transfer
+ * type becomes two-byte. See spi_set_legacy() for details.
+ *
+ * In legacy mode, simply write to the SPI_DOUT register will trigger
+ * the transfer.
+ *
+ * If @dout == NULL, which means no actual data needs to be sent out,
+ * then the function will shift out 0x00 in order to shift in data.
+ * The XFER_RDY flag is checked every time before accessing SPI_DOUT
+ * and SPI_DIN register.
+ *
+ * The number of transfers to be triggerred is decided by @bytelen.
+ *
+ * Return: 0 - cool
+ * -ETIMEDOUT - XFER_RDY flag timeout
+ */
+static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
+ const void *dout, void *din)
+{
+ const u8 *dout_8;
+ u8 *din_8;
+ int ret;
+
+ /* Use 0x00 as dummy dout */
+ const u8 dummy_dout = 0x0;
+ u32 pending_dout = 0x0;
+
+ /* dout_8: pointer of current dout */
+ dout_8 = dout;
+ /* din_8: pointer of current din */
+ din_8 = din;
+
+ while (bytelen) {
+ ret = wait_for_bit(__func__, &reg->ctrl,
+ MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+ if (ret)
+ return ret;
+
+ if (dout)
+ pending_dout = (u32)*dout_8;
+ else
+ pending_dout = (u32)dummy_dout;
+
+ /* Trigger the xfer */
+ writel(pending_dout, &reg->dout);
+
+ if (din) {
+ ret = wait_for_bit(__func__, &reg->ctrl,
+ MVEBU_SPI_A3700_XFER_RDY,
+ true, 100, false);
+ if (ret)
+ return ret;
+
+ /* Read what is transferred in */
+ *din_8 = (u8)readl(&reg->din);
+ }
+
+ /* Don't increment the current pointer if NULL */
+ if (dout)
+ dout_8++;
+ if (din)
+ din_8++;
+
+ bytelen--;
+ }
+
+ return 0;
+}
+
+static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+ struct udevice *bus = dev->parent;
+ struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+ struct spi_reg *reg = plat->spireg;
+ unsigned int bytelen;
+ int ret;
+
+ bytelen = bitlen / 8;
+
+ if (dout && din)
+ debug("This is a duplex transfer.\n");
+
+ /* Activate CS */
+ if (flags & SPI_XFER_BEGIN) {
+ debug("SPI: activate cs.\n");
+ spi_cs_activate(reg, spi_chip_select(dev));
+ }
+
+ /* Send and/or receive */
+ if (dout || din) {
+ ret = spi_legacy_shift_byte(reg, bytelen, dout, din);
+ if (ret)
+ return ret;
+ }
+
+ /* Deactivate CS */
+ if (flags & SPI_XFER_END) {
+ ret = wait_for_bit(__func__, &reg->ctrl,
+ MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+ if (ret)
+ return ret;
+
+ debug("SPI: deactivate cs.\n");
+ spi_cs_deactivate(reg, spi_chip_select(dev));
+ }
+
+ return 0;
+}
+
+static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
+{
+ struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+ struct spi_reg *reg = plat->spireg;
+ u32 data;
+
+ data = readl(&reg->cfg);
+
+ /* Set Prescaler */
+ data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
+
+ /* Calculate Prescaler = (spi_input_freq / spi_max_freq) */
+ if (hz > plat->frequency)
+ hz = plat->frequency;
+ data |= plat->clock / hz;
+
+ writel(data, &reg->cfg);
+
+ return 0;
+}
+
+static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
+{
+ struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+ struct spi_reg *reg = plat->spireg;
+
+ /*
+ * Set SPI polarity
+ * 0: Serial interface clock is low when inactive
+ * 1: Serial interface clock is high when inactive
+ */
+ if (mode & SPI_CPOL)
+ setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
+ else
+ clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
+ if (mode & SPI_CPHA)
+ setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
+ else
+ clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
+
+ return 0;
+}
+
+static int mvebu_spi_probe(struct udevice *bus)
+{
+ struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+ struct spi_reg *reg = plat->spireg;
+ u32 data;
+ int ret;
+
+ /*
+ * Settings SPI controller to be working in legacy mode, which
+ * means use only DO pin (I/O 1) for Data Out, and DI pin (I/O 0)
+ * for Data In.
+ */
+
+ /* Flush read/write FIFO */
+ data = readl(&reg->cfg);
+ writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, &reg->cfg);
+ ret = wait_for_bit(__func__, &reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
+ false, 1000, false);
+ if (ret)
+ return ret;
+
+ /* Disable FIFO mode */
+ data &= ~MVEBU_SPI_A3700_FIFO_EN;
+
+ /* Always shift 1 byte at a time */
+ data &= ~MVEBU_SPI_A3700_BYTE_LEN;
+
+ writel(data, &reg->cfg);
+
+ return 0;
+}
+
+static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
+{
+ struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+
+ plat->spireg = (struct spi_reg *)dev_get_addr(bus);
+
+ /*
+ * FIXME
+ * Right now, mvebu does not have a clock infrastructure in U-Boot
+ * which should be used to query the input clock to the SPI
+ * controller. Once this clock driver is integrated into U-Boot
+ * it should be used to read the input clock and the DT property
+ * can be removed.
+ */
+ plat->clock = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+ "clock-frequency", 160000);
+ plat->frequency = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+ "spi-max-frequency", 40000);
+
+ return 0;
+}
+
+static const struct dm_spi_ops mvebu_spi_ops = {
+ .xfer = mvebu_spi_xfer,
+ .set_speed = mvebu_spi_set_speed,
+ .set_mode = mvebu_spi_set_mode,
+ /*
+ * cs_info is not needed, since we require all chip selects to be
+ * in the device tree explicitly
+ */
+};
+
+static const struct udevice_id mvebu_spi_ids[] = {
+ { .compatible = "marvell,armada-3700-spi" },
+ { }
+};
+
+U_BOOT_DRIVER(mvebu_spi) = {
+ .name = "mvebu_spi",
+ .id = UCLASS_SPI,
+ .of_match = mvebu_spi_ids,
+ .ops = &mvebu_spi_ops,
+ .ofdata_to_platdata = mvebu_spi_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct mvebu_spi_platdata),
+ .probe = mvebu_spi_probe,
+};
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 61e13d76e6..b9c5fbe381 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -21,6 +21,15 @@ config USB_XHCI_DWC3
Say Y or if your system has a Dual Role SuperSpeed
USB controller based on the DesignWare USB3 IP Core.
+config USB_XHCI_MVEBU
+ bool "MVEBU USB 3.0 support"
+ default y
+ depends on ARCH_MVEBU
+ help
+ Choose this option to add support for USB 3.0 driver on mvebu
+ SoCs, which includes Armada8K, Armada3700 and other Armada
+ family SoCs.
+
config USB_XHCI_ROCKCHIP
bool "Support for Rockchip on-chip xHCI USB controller"
depends on ARCH_ROCKCHIP
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index de253284fb..58c0cf54c2 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_USB_XHCI_ZYNQMP) += xhci-zynqmp.o
obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o
obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o
+obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
diff --git a/drivers/usb/host/ehci-marvell.c b/drivers/usb/host/ehci-marvell.c
index 253fcb3c96..464247035e 100644
--- a/drivers/usb/host/ehci-marvell.c
+++ b/drivers/usb/host/ehci-marvell.c
@@ -26,6 +26,16 @@ DECLARE_GLOBAL_DATA_PTR;
#define USB_WINDOW_BASE(i) (0x324 + ((i) << 4))
#define USB_TARGET_DRAM 0x0
+#define USB2_SBUSCFG_OFF 0x90
+
+#define USB_SBUSCFG_BAWR_OFF 0x6
+#define USB_SBUSCFG_BARD_OFF 0x3
+#define USB_SBUSCFG_AHBBRST_OFF 0x0
+
+#define USB_SBUSCFG_BAWR_ALIGN_64B 0x4
+#define USB_SBUSCFG_BARD_ALIGN_64B 0x4
+#define USB_SBUSCFG_AHBBRST_INCR16 0x7
+
/*
* USB 2.0 Bridge Address Decoding registers setup
*/
@@ -41,7 +51,7 @@ struct ehci_mvebu_priv {
* to the common mvebu archticture including the mbus setup, this
* will be the only function needed to configure the access windows
*/
-static void usb_brg_adrdec_setup(u32 base)
+static void usb_brg_adrdec_setup(void *base)
{
const struct mbus_dram_target_info *dram;
int i;
@@ -66,6 +76,29 @@ static void usb_brg_adrdec_setup(u32 base)
}
}
+static void marvell_ehci_powerup_fixup(struct ehci_ctrl *ctrl,
+ uint32_t *status_reg, uint32_t *reg)
+{
+ struct ehci_mvebu_priv *priv = ctrl->priv;
+
+ /*
+ * Set default value for reg SBUSCFG, which is Control for the AMBA
+ * system bus interface:
+ * BAWR = BARD = 4 : Align rd/wr bursts packets larger than 64 bytes
+ * AHBBRST = 7 : Align AHB burst for packets larger than 64 bytes
+ */
+ writel((USB_SBUSCFG_BAWR_ALIGN_64B << USB_SBUSCFG_BAWR_OFF) |
+ (USB_SBUSCFG_BARD_ALIGN_64B << USB_SBUSCFG_BARD_OFF) |
+ (USB_SBUSCFG_AHBBRST_INCR16 << USB_SBUSCFG_AHBBRST_OFF),
+ priv->hcd_base + USB2_SBUSCFG_OFF);
+
+ mdelay(50);
+}
+
+static struct ehci_ops marvell_ehci_ops = {
+ .powerup_fixup = NULL,
+};
+
static int ehci_mvebu_probe(struct udevice *dev)
{
struct ehci_mvebu_priv *priv = dev_get_priv(dev);
@@ -81,21 +114,33 @@ static int ehci_mvebu_probe(struct udevice *dev)
return -ENXIO;
}
- usb_brg_adrdec_setup(priv->hcd_base);
+ /*
+ * For SoCs without hlock like Armada3700 we need to program the sbuscfg
+ * reg to guarantee AHB master's burst will not overrun or underrun
+ * the FIFO. Otherwise all USB2 write option will fail.
+ * Also, the address decoder doesn't need to get setup with this
+ * SoC, so don't call usb_brg_adrdec_setup().
+ */
+ if (of_device_is_compatible(dev, "marvell,armada3700-ehci"))
+ marvell_ehci_ops.powerup_fixup = marvell_ehci_powerup_fixup;
+ else
+ usb_brg_adrdec_setup((void *)priv->hcd_base);
hccr = (struct ehci_hccr *)(priv->hcd_base + 0x100);
hcor = (struct ehci_hcor *)
- ((u32)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ ((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
- debug("ehci-marvell: init hccr %x and hcor %x hc_length %d\n",
- (u32)hccr, (u32)hcor,
- (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ debug("ehci-marvell: init hccr %lx and hcor %lx hc_length %ld\n",
+ (uintptr_t)hccr, (uintptr_t)hcor,
+ (uintptr_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
- return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
+ return ehci_register(dev, hccr, hcor, &marvell_ehci_ops, 0,
+ USB_INIT_HOST);
}
static const struct udevice_id ehci_usb_ids[] = {
{ .compatible = "marvell,orion-ehci", },
+ { .compatible = "marvell,armada3700-ehci", },
{ }
};
diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c
new file mode 100644
index 0000000000..23c241a7c7
--- /dev/null
+++ b/drivers/usb/host/xhci-mvebu.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2015 Marvell International Ltd.
+ *
+ * MVEBU USB HOST xHCI Controller
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <usb.h>
+#include <asm/gpio.h>
+
+#include "xhci.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mvebu_xhci_platdata {
+ fdt_addr_t hcd_base;
+};
+
+/**
+ * Contains pointers to register base addresses
+ * for the usb controller.
+ */
+struct mvebu_xhci {
+ struct xhci_ctrl ctrl; /* Needs to come first in this struct! */
+ struct usb_platdata usb_plat;
+ struct xhci_hccr *hcd;
+};
+
+/*
+ * Dummy implementation that can be overwritten by a board
+ * specific function
+ */
+__weak int board_xhci_enable(void)
+{
+ return 0;
+}
+
+static int xhci_usb_probe(struct udevice *dev)
+{
+ struct mvebu_xhci_platdata *plat = dev_get_platdata(dev);
+ struct mvebu_xhci *ctx = dev_get_priv(dev);
+ struct xhci_hcor *hcor;
+ int len;
+
+ ctx->hcd = (struct xhci_hccr *)plat->hcd_base;
+ len = HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase));
+ hcor = (struct xhci_hcor *)((uintptr_t)ctx->hcd + len);
+
+ /* Enable USB xHCI (VBUS, reset etc) in board specific code */
+ board_xhci_enable();
+
+ return xhci_register(dev, ctx->hcd, hcor);
+}
+
+static int xhci_usb_remove(struct udevice *dev)
+{
+ return xhci_deregister(dev);
+}
+
+static int xhci_usb_ofdata_to_platdata(struct udevice *dev)
+{
+ struct mvebu_xhci_platdata *plat = dev_get_platdata(dev);
+
+ /*
+ * Get the base address for XHCI controller from the device node
+ */
+ plat->hcd_base = dev_get_addr(dev);
+ if (plat->hcd_base == FDT_ADDR_T_NONE) {
+ debug("Can't get the XHCI register base address\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id xhci_usb_ids[] = {
+ { .compatible = "marvell,armada3700-xhci" },
+ { .compatible = "marvell,armada-8k-xhci" },
+ { }
+};
+
+U_BOOT_DRIVER(usb_xhci) = {
+ .name = "xhci_mvebu",
+ .id = UCLASS_USB,
+ .of_match = xhci_usb_ids,
+ .ofdata_to_platdata = xhci_usb_ofdata_to_platdata,
+ .probe = xhci_usb_probe,
+ .remove = xhci_usb_remove,
+ .ops = &xhci_usb_ops,
+ .platdata_auto_alloc_size = sizeof(struct mvebu_xhci_platdata),
+ .priv_auto_alloc_size = sizeof(struct mvebu_xhci),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/include/configs/mvebu_db-88f3720.h b/include/configs/mvebu_db-88f3720.h
new file mode 100644
index 0000000000..e785f241f8
--- /dev/null
+++ b/include/configs/mvebu_db-88f3720.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _CONFIG_MVEBU_DB_88F3720_H
+#define _CONFIG_MVEBU_DB_88F3720_H
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+#define CONFIG_ARCH_EARLY_INIT_R
+
+#define CONFIG_SYS_TEXT_BASE 0x00000000
+
+/* additions for new ARM relocation support */
+#define CONFIG_SYS_SDRAM_BASE 0x00000000
+
+#define CONFIG_NR_DRAM_BANKS 1
+
+/* auto boot */
+#define CONFIG_PREBOOT
+
+#define CONFIG_BAUDRATE 115200
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, \
+ 115200, 230400, 460800, 921600 }
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CONFIG_CMDLINE_TAG /* enable passing of ATAGs */
+#define CONFIG_INITRD_TAG /* enable INITRD tag */
+#define CONFIG_SETUP_MEMORY_TAGS /* enable memory tag */
+
+#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buff Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \
+ +sizeof(CONFIG_SYS_PROMPT) + 16) /* Print Buff */
+
+/*
+ * Size of malloc() pool
+ */
+#define CONFIG_SYS_MALLOC_LEN (4 << 20) /* 4MiB for malloc() */
+
+/*
+ * Other required minimal configurations
+ */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_CONSOLE_INFO_QUIET /* some code reduction */
+#define CONFIG_ARCH_CPU_INIT /* call arch_cpu_init() */
+#define CONFIG_BOARD_EARLY_INIT_F /* call board_init_f for early inits */
+#define CONFIG_SYS_LOAD_ADDR 0x00800000 /* default load adr- 8M */
+#define CONFIG_SYS_MEMTEST_START 0x00800000 /* 8M */
+#define CONFIG_SYS_MEMTEST_END 0x00ffffff /*(_16M -1) */
+#define CONFIG_SYS_RESET_ADDRESS 0xffff0000 /* Rst Vector Adr */
+#define CONFIG_SYS_MAXARGS 32 /* max number of command args */
+
+#define CONFIG_SYS_CONSOLE_INFO_QUIET /* don't print console @ startup */
+#define CONFIG_SYS_ALT_MEMTEST
+
+/* End of 16M scrubbed by training in bootrom */
+#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + 0xFF0000)
+
+/*
+ * I2C
+ */
+#define CONFIG_I2C_MV
+#define CONFIG_SYS_I2C_SLAVE 0x0
+
+/*
+ * SPI Flash configuration
+ */
+#define CONFIG_ENV_SPI_BUS 0
+#define CONFIG_ENV_SPI_CS 0
+
+/* SPI NOR flash default params, used by sf commands */
+#define CONFIG_SF_DEFAULT_SPEED 1000000
+#define CONFIG_SF_DEFAULT_MODE SPI_MODE_0
+#define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE
+
+/* Environment in SPI NOR flash */
+#define CONFIG_SYS_NO_FLASH /* Declare no flash (NOR/SPI) */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_OFFSET 0x180000 /* as Marvell U-Boot version */
+#define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */
+#define CONFIG_ENV_SECT_SIZE (64 << 10) /* 64KiB sectors */
+
+/*
+ * Ethernet Driver configuration
+ */
+#define CONFIG_MVNETA /* Enable Marvell Gbe Controller Driver */
+#define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */
+#define CONFIG_PHY_GIGE /* GbE speed/duplex detect */
+#define CONFIG_ARP_TIMEOUT 200
+#define CONFIG_NET_RETRY_COUNT 50
+
+/* USB 2.0 */
+#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3
+
+/* USB 3.0 */
+#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 3
+
+#define CONFIG_USB_MAX_CONTROLLER_COUNT (CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS + \
+ CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS)
+
+/* USB ethernet */
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_ASIX
+#define CONFIG_USB_ETHER_MCS7830
+#define CONFIG_USB_ETHER_RTL8152
+#define CONFIG_USB_ETHER_SMSC95XX
+
+/*
+ * SATA/SCSI/AHCI configuration
+ */
+#define CONFIG_SCSI
+#define CONFIG_SCSI_AHCI
+#define CONFIG_SCSI_AHCI_PLAT
+#define CONFIG_LIBATA
+#define CONFIG_LBA48
+#define CONFIG_SYS_64BIT_LBA
+
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID 2
+#define CONFIG_SYS_SCSI_MAX_LUN 1
+#define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+ CONFIG_SYS_SCSI_MAX_LUN)
+
+#define CONFIG_SUPPORT_VFAT
+
+/* DISK Partition support */
+#define CONFIG_EFI_PARTITION
+#define CONFIG_DOS_PARTITION
+#define CONFIG_MAC_PARTITION
+#define CONFIG_ISO_PARTITION /* Experimental */
+
+#define CONFIG_CMD_PART
+#define CONFIG_PARTITION_UUIDS
+
+#endif /* _CONFIG_MVEBU_DB_88F3720_H */
diff --git a/include/configs/mvebu_db-88f7040.h b/include/configs/mvebu_db-88f7040.h
new file mode 100644
index 0000000000..cfb0191e8d
--- /dev/null
+++ b/include/configs/mvebu_db-88f7040.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _CONFIG_MVEBU_DB_88F7040_H
+#define _CONFIG_MVEBU_DB_88F7040_H
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+#define CONFIG_SYS_TCLK 250000000 /* 250MHz */
+
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+#define CONFIG_ARCH_EARLY_INIT_R
+#define CONFIG_BOARD_LATE_INIT
+
+#define CONFIG_SYS_TEXT_BASE 0x00000000
+
+/* additions for new ARM relocation support */
+#define CONFIG_SYS_SDRAM_BASE 0x00000000
+
+#define CONFIG_NR_DRAM_BANKS 1
+
+/* auto boot */
+#define CONFIG_PREBOOT
+
+#define CONFIG_BAUDRATE 115200
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, \
+ 115200, 230400, 460800, 921600 }
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CONFIG_CMDLINE_TAG /* enable passing of ATAGs */
+#define CONFIG_INITRD_TAG /* enable INITRD tag */
+#define CONFIG_SETUP_MEMORY_TAGS /* enable memory tag */
+
+#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buff Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \
+ +sizeof(CONFIG_SYS_PROMPT) + 16) /* Print Buff */
+
+/*
+ * Size of malloc() pool
+ */
+#define CONFIG_SYS_MALLOC_LEN (4 << 20) /* 4MiB for malloc() */
+
+/*
+ * Other required minimal configurations
+ */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_CONSOLE_INFO_QUIET /* some code reduction */
+#define CONFIG_ARCH_CPU_INIT /* call arch_cpu_init() */
+#define CONFIG_BOARD_EARLY_INIT_F /* call board_init_f for early inits */
+#define CONFIG_SYS_LOAD_ADDR 0x00800000 /* default load adr- 8M */
+#define CONFIG_SYS_MEMTEST_START 0x00800000 /* 8M */
+#define CONFIG_SYS_MEMTEST_END 0x00ffffff /*(_16M -1) */
+#define CONFIG_SYS_RESET_ADDRESS 0xffff0000 /* Rst Vector Adr */
+#define CONFIG_SYS_MAXARGS 32 /* max number of command args */
+
+#define CONFIG_SYS_CONSOLE_INFO_QUIET /* don't print console @ startup */
+#define CONFIG_SYS_ALT_MEMTEST
+
+/* End of 16M scrubbed by training in bootrom */
+#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + 0xFF0000)
+
+/*
+ * SPI Flash configuration
+ */
+#define CONFIG_KIRKWOOD_SPI
+#define CONFIG_ENV_SPI_BUS 0
+#define CONFIG_ENV_SPI_CS 0
+
+/* SPI NOR flash default params, used by sf commands */
+#define CONFIG_SF_DEFAULT_SPEED 1000000
+#define CONFIG_SF_DEFAULT_MODE SPI_MODE_0
+#define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE
+
+/* Environment in SPI NOR flash */
+#define CONFIG_SYS_NO_FLASH /* Declare no flash (NOR/SPI) */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_OFFSET 0x180000 /* as Marvell U-Boot version */
+#define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */
+#define CONFIG_ENV_SECT_SIZE (64 << 10) /* 64KiB sectors */
+
+/* USB 2.0 */
+#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3
+
+/* USB 3.0 */
+#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 3
+
+#define CONFIG_USB_MAX_CONTROLLER_COUNT (CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS + \
+ CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS)
+
+/* USB ethernet */
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_ASIX
+#define CONFIG_USB_ETHER_MCS7830
+#define CONFIG_USB_ETHER_RTL8152
+#define CONFIG_USB_ETHER_SMSC95XX
+
+/*
+ * SATA/SCSI/AHCI configuration
+ */
+#define CONFIG_SCSI
+#define CONFIG_SCSI_AHCI
+#define CONFIG_SCSI_AHCI_PLAT
+#define CONFIG_LIBATA
+#define CONFIG_LBA48
+#define CONFIG_SYS_64BIT_LBA
+
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID 2
+#define CONFIG_SYS_SCSI_MAX_LUN 1
+#define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+ CONFIG_SYS_SCSI_MAX_LUN)
+
+#define CONFIG_SUPPORT_VFAT
+
+/* DISK Partition support */
+#define CONFIG_EFI_PARTITION
+#define CONFIG_DOS_PARTITION
+#define CONFIG_MAC_PARTITION
+#define CONFIG_ISO_PARTITION /* Experimental */
+
+#define CONFIG_CMD_PART
+#define CONFIG_PARTITION_UUIDS
+
+#endif /* _CONFIG_MVEBU_DB_88F7040_H */
diff --git a/include/dt-bindings/comphy/comphy_data.h b/include/dt-bindings/comphy/comphy_data.h
new file mode 100644
index 0000000000..a3a6b405eb
--- /dev/null
+++ b/include/dt-bindings/comphy/comphy_data.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _COMPHY_DATA_H_
+#define _COMPHY_DATA_H_
+
+#define PHY_SPEED_1_25G 0
+#define PHY_SPEED_1_5G 1
+#define PHY_SPEED_2_5G 2
+#define PHY_SPEED_3G 3
+#define PHY_SPEED_3_125G 4
+#define PHY_SPEED_5G 5
+#define PHY_SPEED_6G 6
+#define PHY_SPEED_6_25G 7
+#define PHY_SPEED_10_3125G 8
+#define PHY_SPEED_MAX 9
+#define PHY_SPEED_INVALID 0xff
+
+#define PHY_TYPE_UNCONNECTED 0
+#define PHY_TYPE_PEX0 1
+#define PHY_TYPE_PEX1 2
+#define PHY_TYPE_PEX2 3
+#define PHY_TYPE_PEX3 4
+#define PHY_TYPE_SATA0 5
+#define PHY_TYPE_SATA1 6
+#define PHY_TYPE_SATA2 7
+#define PHY_TYPE_SATA3 8
+#define PHY_TYPE_SGMII0 9
+#define PHY_TYPE_SGMII1 10
+#define PHY_TYPE_SGMII2 11
+#define PHY_TYPE_SGMII3 12
+#define PHY_TYPE_QSGMII 13
+#define PHY_TYPE_USB3_HOST0 14
+#define PHY_TYPE_USB3_HOST1 15
+#define PHY_TYPE_USB3_DEVICE 16
+#define PHY_TYPE_XAUI0 17
+#define PHY_TYPE_XAUI1 18
+#define PHY_TYPE_XAUI2 19
+#define PHY_TYPE_XAUI3 20
+#define PHY_TYPE_RXAUI0 21
+#define PHY_TYPE_RXAUI1 22
+#define PHY_TYPE_KR 23
+#define PHY_TYPE_MAX 24
+#define PHY_TYPE_INVALID 0xff
+
+#define PHY_POLARITY_NO_INVERT 0
+#define PHY_POLARITY_TXD_INVERT 1
+#define PHY_POLARITY_RXD_INVERT 2
+#define PHY_POLARITY_ALL_INVERT \
+ (PHY_POLARITY_TXD_INVERT | PHY_POLARITY_RXD_INVERT)
+
+#define UTMI_PHY_TO_USB_HOST0 0
+#define UTMI_PHY_TO_USB_HOST1 1
+#define UTMI_PHY_TO_USB_DEVICE0 2
+#define UTMI_PHY_INVALID 0xff
+
+#endif /* _COMPHY_DATA_H_ */
+