diff options
24 files changed, 1486 insertions, 186 deletions
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 1964d3d9d1..570e089573 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -75,6 +75,7 @@ dtb-$(CONFIG_ARCH_MVEBU) += \ armada-388-gp.dtb \ armada-385-amc.dtb \ armada-7040-db.dtb \ + armada-8040-db.dtb \ armada-xp-gp.dtb \ armada-xp-maxbcm.dtb \ armada-xp-synology-ds414.dtb \ diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts index 7d0059afe5..b8fe5a9cb9 100644 --- a/arch/arm/dts/armada-7040-db.dts +++ b/arch/arm/dts/armada-7040-db.dts @@ -152,7 +152,7 @@ status = "okay"; }; -&comphy_cp110 { +&cpm_comphy { phy0 { phy-type = <PHY_TYPE_SGMII2>; phy-speed = <PHY_SPEED_3_125G>; @@ -184,10 +184,10 @@ }; }; -&utmi0 { +&cpm_utmi0 { status = "okay"; }; -&utmi1 { +&cpm_utmi1 { status = "okay"; }; diff --git a/arch/arm/dts/armada-8020.dtsi b/arch/arm/dts/armada-8020.dtsi new file mode 100644 index 0000000000..048e5cf516 --- /dev/null +++ b/arch/arm/dts/armada-8020.dtsi @@ -0,0 +1,56 @@ +/* + * 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 8020 SoC, made of an AP806 Dual and + * two CP110. + */ + +#include "armada-ap806-dual.dtsi" +#include "armada-cp110-master.dtsi" +#include "armada-cp110-slave.dtsi" + +/ { + model = "Marvell Armada 8020"; + compatible = "marvell,armada8020", "marvell,armada-ap806-dual", + "marvell,armada-ap806"; +}; diff --git a/arch/arm/dts/armada-8040-db.dts b/arch/arm/dts/armada-8040-db.dts new file mode 100644 index 0000000000..7fb674b8b7 --- /dev/null +++ b/arch/arm/dts/armada-8040-db.dts @@ -0,0 +1,239 @@ +/* + * 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 8040 Development board platform + */ + +#include "armada-8040.dtsi" + +/ { + model = "Marvell Armada 8040 DB board"; + compatible = "marvell,armada8040-db", "marvell,armada8040", + "marvell,armada-ap806-quad", "marvell,armada-ap806"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + i2c0 = &cpm_i2c0; + spi0 = &spi0; + }; + + 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>; + }; + }; + }; +}; + +/* Accessible over the mini-USB CON9 connector on the main board */ +&uart0 { + status = "okay"; +}; + + +/* CON5 on CP0 expansion */ +&cpm_pcie2 { + status = "okay"; +}; + +&cpm_i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +/* CON4 on CP0 expansion */ +&cpm_sata0 { + status = "okay"; +}; + +/* CON9 on CP0 expansion */ +&cpm_usb3_0 { + status = "okay"; +}; + +/* CON10 on CP0 expansion */ +&cpm_usb3_1 { + status = "okay"; +}; + +/* CON5 on CP1 expansion */ +&cps_pcie2 { + status = "okay"; +}; + +&cps_i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +/* CON4 on CP1 expansion */ +&cps_sata0 { + status = "okay"; +}; + +/* CON9 on CP1 expansion */ +&cps_usb3_0 { + status = "okay"; +}; + +/* CON10 on CP1 expansion */ +&cps_usb3_1 { + status = "okay"; +}; + +&cpm_comphy { + /* + * Serdes Configuration: + * Lane 0: SGMII2 + * Lane 1: USB3_HOST0 + * Lane 2: KR (10G) + * Lane 3: SATA1 + * Lane 4: USB3_HOST1 + * Lane 5: PEX2x1 + */ + phy0 { + phy-type = <PHY_TYPE_SGMII2>; + phy-speed = <PHY_SPEED_3_125G>; + }; + + phy1 { + phy-type = <PHY_TYPE_USB3_HOST0>; + }; + + phy2 { + phy-type = <PHY_TYPE_KR>; + }; + + phy3 { + phy-type = <PHY_TYPE_SATA1>; + }; + + phy4 { + phy-type = <PHY_TYPE_USB3_HOST1>; + }; + + phy5 { + phy-type = <PHY_TYPE_PEX2>; + }; +}; + +&cps_comphy { + /* + * Serdes Configuration: + * Lane 0: SGMII2 + * Lane 1: USB3_HOST0 + * Lane 2: KR (10G) + * Lane 3: SATA1 + * Lane 4: Unconnected + * Lane 5: PEX2x1 + */ + phy0 { + phy-type = <PHY_TYPE_SGMII2>; + phy-speed = <PHY_SPEED_3_125G>; + }; + + phy1 { + phy-type = <PHY_TYPE_USB3_HOST0>; + }; + + phy2 { + phy-type = <PHY_TYPE_KR>; + }; + + phy3 { + phy-type = <PHY_TYPE_SATA1>; + }; + + phy4 { + phy-type = <PHY_TYPE_UNCONNECTED>; + }; + + phy5 { + phy-type = <PHY_TYPE_PEX2>; + }; +}; + +&cpm_utmi0 { + status = "okay"; +}; + +&cpm_utmi1 { + status = "okay"; +}; + +&cps_utmi0 { + status = "okay"; +}; diff --git a/arch/arm/dts/armada-8040.dtsi b/arch/arm/dts/armada-8040.dtsi new file mode 100644 index 0000000000..9c1b28c476 --- /dev/null +++ b/arch/arm/dts/armada-8040.dtsi @@ -0,0 +1,56 @@ +/* + * 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 8040 SoC, made of an AP806 Quad and + * two CP110. + */ + +#include "armada-ap806-quad.dtsi" +#include "armada-cp110-master.dtsi" +#include "armada-cp110-slave.dtsi" + +/ { + model = "Marvell Armada 8040"; + compatible = "marvell,armada8040", "marvell,armada-ap806-quad", + "marvell,armada-ap806"; +}; diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi index 7da98bf5cb..422d754401 100644 --- a/arch/arm/dts/armada-cp110-master.dtsi +++ b/arch/arm/dts/armada-cp110-master.dtsi @@ -149,7 +149,7 @@ status = "disabled"; }; - comphy_cp110: comphy@441000 { + cpm_comphy: comphy@441000 { compatible = "marvell,mvebu-comphy", "marvell,comphy-cp110"; reg = <0x441000 0x8>, <0x120000 0x8>; @@ -157,7 +157,7 @@ max-lanes = <6>; }; - utmi0: utmi@580000 { + cpm_utmi0: utmi@580000 { compatible = "marvell,mvebu-utmi-2.6.0"; reg = <0x580000 0x1000>, /* utmi-unit */ <0x440420 0x4>, /* usb-cfg */ @@ -166,7 +166,7 @@ status = "disabled"; }; - utmi1: utmi@581000 { + cpm_utmi1: utmi@581000 { compatible = "marvell,mvebu-utmi-2.6.0"; reg = <0x581000 0x1000>, /* utmi-unit */ <0x440420 0x4>, /* usb-cfg */ diff --git a/arch/arm/dts/armada-cp110-slave.dtsi b/arch/arm/dts/armada-cp110-slave.dtsi new file mode 100644 index 0000000000..a7f77b9515 --- /dev/null +++ b/arch/arm/dts/armada-cp110-slave.dtsi @@ -0,0 +1,268 @@ +/* + * 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 Slave. + */ + +#include <dt-bindings/comphy/comphy_data.h> + +/ { + cp110-slave { + #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 0xf4000000 0x2000000>; + + cps_syscon0: system-controller@440000 { + compatible = "marvell,cp110-system-controller0", + "syscon"; + reg = <0x440000 0x1000>; + #clock-cells = <2>; + core-clock-output-names = + "cps-apll", "cps-ppv2-core", "cps-eip", + "cps-core", "cps-nand-core"; + gate-clock-output-names = + "cps-audio", "cps-communit", "cps-nand", + "cps-ppv2", "cps-sdio", "cps-mg-domain", + "cps-mg-core", "cps-xor1", "cps-xor0", + "cps-gop-dp", "none", "cps-pcie_x10", + "cps-pcie_x11", "cps-pcie_x4", "cps-pcie-xor", + "cps-sata", "cps-sata-usb", "cps-main", + "cps-sd-mmc", "none", "none", + "cps-slow-io", "cps-usb3h0", "cps-usb3h1", + "cps-usb3dev", "cps-eip150", "cps-eip197"; + }; + + cps_sata0: sata@540000 { + compatible = "marvell,armada-8k-ahci"; + reg = <0x540000 0x30000>; + interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cps_syscon0 1 15>; + status = "disabled"; + }; + + cps_usb3_0: usb3@500000 { + compatible = "marvell,armada-8k-xhci", + "generic-xhci"; + reg = <0x500000 0x4000>; + dma-coherent; + interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cps_syscon0 1 22>; + status = "disabled"; + }; + + cps_usb3_1: usb3@510000 { + compatible = "marvell,armada-8k-xhci", + "generic-xhci"; + reg = <0x510000 0x4000>; + dma-coherent; + interrupts = <GIC_SPI 285 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cps_syscon0 1 23>; + status = "disabled"; + }; + + cps_xor0: xor@6a0000 { + compatible = "marvell,armada-7k-xor", "marvell,xor-v2"; + reg = <0x6a0000 0x1000>, + <0x6b0000 0x1000>; + dma-coherent; + msi-parent = <&gic_v2m0>; + clocks = <&cps_syscon0 1 8>; + }; + + cps_xor1: xor@6c0000 { + compatible = "marvell,armada-7k-xor", "marvell,xor-v2"; + reg = <0x6c0000 0x1000>, + <0x6d0000 0x1000>; + dma-coherent; + msi-parent = <&gic_v2m0>; + clocks = <&cps_syscon0 1 7>; + }; + + cps_spi0: spi@700600 { + compatible = "marvell,armada-380-spi"; + reg = <0x700600 0x50>; + #address-cells = <0x1>; + #size-cells = <0x0>; + cell-index = <1>; + clocks = <&cps_syscon0 0 3>; + status = "disabled"; + }; + + cps_spi1: spi@700680 { + compatible = "marvell,armada-380-spi"; + reg = <0x700680 0x50>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <2>; + clocks = <&cps_syscon0 1 21>; + status = "disabled"; + }; + + cps_i2c0: i2c@701000 { + compatible = "marvell,mv78230-i2c"; + reg = <0x701000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cps_syscon0 1 21>; + status = "disabled"; + }; + + cps_i2c1: i2c@701100 { + compatible = "marvell,mv78230-i2c"; + reg = <0x701100 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cps_syscon0 1 21>; + status = "disabled"; + }; + + cps_comphy: comphy@441000 { + compatible = "marvell,mvebu-comphy", "marvell,comphy-cp110"; + reg = <0x441000 0x8>, + <0x120000 0x8>; + mux-bitcount = <4>; + max-lanes = <6>; + }; + + cps_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"; + }; + }; + + cps_pcie0: pcie@f4600000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf4600000 0 0x10000>, + <0 0xfaf00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + msi-parent = <&gic_v2m0>; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xfd000000 0 0xfd000000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xfa000000 0 0xfa000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>; + num-lanes = <1>; + clocks = <&cps_syscon0 1 13>; + status = "disabled"; + }; + + cps_pcie1: pcie@f4620000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf4620000 0 0x10000>, + <0 0xfbf00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + msi-parent = <&gic_v2m0>; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xfd010000 0 0xfd010000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xfb000000 0 0xfb000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>; + + num-lanes = <1>; + clocks = <&cps_syscon0 1 11>; + status = "disabled"; + }; + + cps_pcie2: pcie@f4640000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf4640000 0 0x10000>, + <0 0xfcf00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + msi-parent = <&gic_v2m0>; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xfd020000 0 0xfd020000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xfc000000 0 0xfc000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>; + + num-lanes = <1>; + clocks = <&cps_syscon0 1 12>; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 7733936be5..40476dc421 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -83,8 +83,8 @@ config TARGET_DB_88F6820_AMC bool "Support DB-88F6820-AMC" select 88F6820 -config TARGET_MVEBU_DB_88F7040 - bool "Support DB-88F7040 Armada 7040" +config TARGET_MVEBU_ARMADA_8K + bool "Support Armada 7k/8k platforms" select ARMADA_8K config TARGET_DB_MV784MP_GP @@ -111,7 +111,7 @@ config SYS_BOARD 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 "mvebu_armada-8k" if TARGET_MVEBU_ARMADA_8K default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP default "ds414" if TARGET_DS414 default "maxbcm" if TARGET_MAXBCM @@ -123,7 +123,7 @@ config SYS_CONFIG_NAME 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 "mvebu_armada-8k" if TARGET_MVEBU_ARMADA_8K default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP default "ds414" if TARGET_DS414 default "maxbcm" if TARGET_MAXBCM @@ -135,7 +135,7 @@ config SYS_VENDOR 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 "Marvell" if TARGET_MVEBU_ARMADA_8K default "solidrun" if TARGET_CLEARFOG default "Synology" if TARGET_DS414 diff --git a/arch/arm/mach-mvebu/arm64-common.c b/arch/arm/mach-mvebu/arm64-common.c index 7055a81de3..8f026559c2 100644 --- a/arch/arm/mach-mvebu/arm64-common.c +++ b/arch/arm/mach-mvebu/arm64-common.c @@ -17,6 +17,23 @@ DECLARE_GLOBAL_DATA_PTR; /* + * Not all memory is mapped in the MMU. So we need to restrict the + * memory size so that U-Boot does not try to access it. Also, the + * internal registers are located at 0xf000.0000 - 0xffff.ffff. + * Currently only 2GiB are mapped for system memory. This is what + * we pass to the U-Boot subsystem here. + */ +#define USABLE_RAM_SIZE 0x80000000 + +ulong board_get_usable_ram_top(ulong total_size) +{ + if (gd->ram_size > USABLE_RAM_SIZE) + return USABLE_RAM_SIZE; + + return gd->ram_size; +} + +/* * 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. @@ -109,12 +126,20 @@ 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; + int i; + + /* + * Loop over all MISC uclass drivers to call the comphy code + * and init all CP110 devices enabled in the DT + */ + i = 0; + while (1) { + /* Call the comphy code via the MISC uclass driver */ + ret = uclass_get_device(UCLASS_MISC, i++, &dev); + + /* We're done, once no further CP110 device is found */ + if (ret) + break; } /* Cause the SATA device to do its early init */ diff --git a/arch/arm/mach-mvebu/armada8k/cpu.c b/arch/arm/mach-mvebu/armada8k/cpu.c index 036430c46c..2719d68e07 100644 --- a/arch/arm/mach-mvebu/armada8k/cpu.c +++ b/arch/arm/mach-mvebu/armada8k/cpu.c @@ -39,7 +39,7 @@ static struct mm_region mvebu_mem_map[] = { PTE_BLOCK_NON_SHARE }, { - /* SRAM, MMIO regions - CP110 region */ + /* SRAM, MMIO regions - CP110 master region */ .phys = 0xf2000000UL, .virt = 0xf2000000UL, .size = 0x02000000UL, /* 32MiB internal registers */ @@ -47,6 +47,22 @@ static struct mm_region mvebu_mem_map[] = { PTE_BLOCK_NON_SHARE }, { + /* SRAM, MMIO regions - CP110 slave region */ + .phys = 0xf4000000UL, + .virt = 0xf4000000UL, + .size = 0x02000000UL, /* 32MiB internal registers */ + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE + }, + { + /* PCI regions */ + .phys = 0xf8000000UL, + .virt = 0xf8000000UL, + .size = 0x08000000UL, /* 128MiB PCI space (master & slave) */ + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE + }, + { /* List terminator */ 0, } diff --git a/board/Marvell/mvebu_armada-8k/MAINTAINERS b/board/Marvell/mvebu_armada-8k/MAINTAINERS new file mode 100644 index 0000000000..e0b965dfd6 --- /dev/null +++ b/board/Marvell/mvebu_armada-8k/MAINTAINERS @@ -0,0 +1,7 @@ +MVEBU_ARMADA_8K BOARD +M: Stefan Roese <sr@denx.de> +S: Maintained +F: board/Marvell/mvebu_armada-8k/ +F: include/configs/mvebu_armada-8k.h +F: configs/mvebu_db-88f7040_defconfig +F: configs/mvebu_db-88f8040_defconfig diff --git a/board/Marvell/mvebu_db-88f7040/Makefile b/board/Marvell/mvebu_armada-8k/Makefile index ed39738816..ed39738816 100644 --- a/board/Marvell/mvebu_db-88f7040/Makefile +++ b/board/Marvell/mvebu_armada-8k/Makefile diff --git a/board/Marvell/mvebu_armada-8k/board.c b/board/Marvell/mvebu_armada-8k/board.c new file mode 100644 index 0000000000..7d1b5d9f62 --- /dev/null +++ b/board/Marvell/mvebu_armada-8k/board.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2016 Stefan Roese <sr@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <i2c.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/soc.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Information specific to the DB-88F7040 eval board. We strive to use + * DT for such platform specfic configurations. At some point, this + * might be removed here and implemented via DT. + */ +/* 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]; + + if (of_machine_is_compatible("marvell,armada7040-db")) { + /* 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]; + + if (of_machine_is_compatible("marvell,armada7040-db")) { + /* + * 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/board/Marvell/mvebu_db-88f7040/MAINTAINERS b/board/Marvell/mvebu_db-88f7040/MAINTAINERS deleted file mode 100644 index 820461b213..0000000000 --- a/board/Marvell/mvebu_db-88f7040/MAINTAINERS +++ /dev/null @@ -1,6 +0,0 @@ -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/board.c b/board/Marvell/mvebu_db-88f7040/board.c deleted file mode 100644 index 48bd55c372..0000000000 --- a/board/Marvell/mvebu_db-88f7040/board.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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-88f7040_defconfig b/configs/mvebu_db-88f7040_defconfig index 81152cd783..f153b9cd77 100644 --- a/configs/mvebu_db-88f7040_defconfig +++ b/configs/mvebu_db-88f7040_defconfig @@ -1,8 +1,9 @@ CONFIG_ARM=y CONFIG_ARCH_MVEBU=y CONFIG_SYS_MALLOC_F_LEN=0x2000 -CONFIG_TARGET_MVEBU_DB_88F7040=y +CONFIG_TARGET_MVEBU_ARMADA_8K=y CONFIG_DEFAULT_DEVICE_TREE="armada-7040-db" +CONFIG_SMBIOS_PRODUCT_NAME="" CONFIG_AHCI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SYS_CONSOLE_INFO_QUIET=y @@ -48,3 +49,4 @@ CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_STORAGE=y +CONFIG_SMBIOS_MANUFACTURER="" diff --git a/configs/mvebu_db-88f8040_defconfig b/configs/mvebu_db-88f8040_defconfig new file mode 100644 index 0000000000..61d58b50c2 --- /dev/null +++ b/configs/mvebu_db-88f8040_defconfig @@ -0,0 +1,55 @@ +CONFIG_ARM=y +CONFIG_ARCH_MVEBU=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_TARGET_MVEBU_ARMADA_8K=y +CONFIG_DEFAULT_DEVICE_TREE="armada-8040-db" +CONFIG_SMBIOS_PRODUCT_NAME="" +CONFIG_AHCI=y +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_DISPLAY_BOARDINFO 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_PCI=y +CONFIG_DM_PCI=y +CONFIG_PCIE_DW_MVEBU=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 +CONFIG_SMBIOS_MANUFACTURER="" diff --git a/drivers/block/sata_mv.c b/drivers/block/sata_mv.c index 414d2dc464..78e3da442d 100644 --- a/drivers/block/sata_mv.c +++ b/drivers/block/sata_mv.c @@ -572,6 +572,7 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; struct crqb *req; int slot; + u32 start; if (len >= 64 * 1024) { printf("We only support <64K transfers for now\n"); @@ -628,7 +629,9 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, CRQB_SECTCOUNT_COUNT_EXP_MASK; /* Flush data */ - flush_dcache_range((u32)req, (u32)req + sizeof(*req)); + start = (u32)req & ~(ARCH_DMA_MINALIGN - 1); + flush_dcache_range(start, + start + ALIGN(sizeof(*req), ARCH_DMA_MINALIGN)); /* Trigger operation */ slot = get_next_reqip(port); @@ -643,8 +646,11 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, process_responses(port); /* Invalidate data on read */ - if (buffer && len) - invalidate_dcache_range((u32)buffer, (u32)buffer + len); + if (buffer && len) { + start = (u32)buffer & ~(ARCH_DMA_MINALIGN - 1); + invalidate_dcache_range(start, + start + ALIGN(len, ARCH_DMA_MINALIGN)); + } return len; } diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index b8376b4f47..ff2c37006e 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -33,6 +33,16 @@ config PCI_PNP help Enable PCI memory and I/O space resource allocation and assignment. +config PCIE_DW_MVEBU + bool "Enable Armada-8K PCIe driver (DesignWare core)" + default n + depends on DM_PCI + depends on ARMADA_8K + help + Say Y here if you want to enable PCIe controller support on + Armada-8K SoCs. The PCIe controller on Armada-8K is based on + DesignWare hardware. + config PCI_SANDBOX bool "Sandbox PCI support" depends on SANDBOX && DM_PCI diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 9583e91ceb..86717a4fc3 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -30,5 +30,6 @@ obj-$(CONFIG_SH7780_PCI) +=pci_sh7780.o obj-$(CONFIG_PCI_TEGRA) += pci_tegra.o obj-$(CONFIG_TSI108_PCI) += tsi108_pci.o obj-$(CONFIG_WINBOND_83C553) += w83c553f.o +obj-$(CONFIG_PCIE_DW_MVEBU) += pcie_dw_mvebu.o obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o diff --git a/drivers/pci/pcie_dw_mvebu.c b/drivers/pci/pcie_dw_mvebu.c new file mode 100644 index 0000000000..17fa0244d0 --- /dev/null +++ b/drivers/pci/pcie_dw_mvebu.c @@ -0,0 +1,535 @@ +/* + * Copyright (C) 2015 Marvell International Ltd. + * + * Copyright (C) 2016 Stefan Roese <sr@denx.de> + * + * Based on: + * - drivers/pci/pcie_imx.c + * - drivers/pci/pci_mvebu.c + * - drivers/pci/pcie_xilinx.c + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <pci.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* PCI Config space registers */ +#define PCIE_CONFIG_BAR0 0x10 +#define PCIE_LINK_STATUS_REG 0x80 +#define PCIE_LINK_STATUS_SPEED_OFF 16 +#define PCIE_LINK_STATUS_SPEED_MASK (0xf << PCIE_LINK_STATUS_SPEED_OFF) +#define PCIE_LINK_STATUS_WIDTH_OFF 20 +#define PCIE_LINK_STATUS_WIDTH_MASK (0xf << PCIE_LINK_STATUS_WIDTH_OFF) + +/* Resizable bar capability registers */ +#define RESIZABLE_BAR_CAP 0x250 +#define RESIZABLE_BAR_CTL0 0x254 +#define RESIZABLE_BAR_CTL1 0x258 + +/* iATU registers */ +#define PCIE_ATU_VIEWPORT 0x900 +#define PCIE_ATU_REGION_INBOUND (0x1 << 31) +#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31) +#define PCIE_ATU_REGION_INDEX1 (0x1 << 0) +#define PCIE_ATU_REGION_INDEX0 (0x0 << 0) +#define PCIE_ATU_CR1 0x904 +#define PCIE_ATU_TYPE_MEM (0x0 << 0) +#define PCIE_ATU_TYPE_IO (0x2 << 0) +#define PCIE_ATU_TYPE_CFG0 (0x4 << 0) +#define PCIE_ATU_TYPE_CFG1 (0x5 << 0) +#define PCIE_ATU_CR2 0x908 +#define PCIE_ATU_ENABLE (0x1 << 31) +#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30) +#define PCIE_ATU_LOWER_BASE 0x90C +#define PCIE_ATU_UPPER_BASE 0x910 +#define PCIE_ATU_LIMIT 0x914 +#define PCIE_ATU_LOWER_TARGET 0x918 +#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24) +#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19) +#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) +#define PCIE_ATU_UPPER_TARGET 0x91C + +#define PCIE_LINK_CAPABILITY 0x7C +#define PCIE_LINK_CTL_2 0xA0 +#define TARGET_LINK_SPEED_MASK 0xF +#define LINK_SPEED_GEN_1 0x1 +#define LINK_SPEED_GEN_2 0x2 +#define LINK_SPEED_GEN_3 0x3 + +#define PCIE_GEN3_RELATED 0x890 +#define GEN3_EQU_DISABLE (1 << 16) +#define GEN3_ZRXDC_NON_COMP (1 << 0) + +#define PCIE_GEN3_EQU_CTRL 0x8A8 +#define GEN3_EQU_EVAL_2MS_DISABLE (1 << 5) + +#define PCIE_ROOT_COMPLEX_MODE_MASK (0xF << 4) + +#define PCIE_LINK_UP_TIMEOUT_MS 100 + +#define PCIE_GLOBAL_CONTROL 0x8000 +#define PCIE_APP_LTSSM_EN (1 << 2) +#define PCIE_DEVICE_TYPE_OFFSET (4) +#define PCIE_DEVICE_TYPE_MASK (0xF) +#define PCIE_DEVICE_TYPE_EP (0x0) /* Endpoint */ +#define PCIE_DEVICE_TYPE_LEP (0x1) /* Legacy endpoint */ +#define PCIE_DEVICE_TYPE_RC (0x4) /* Root complex */ + +#define PCIE_GLOBAL_STATUS 0x8008 +#define PCIE_GLB_STS_RDLH_LINK_UP (1 << 1) +#define PCIE_GLB_STS_PHY_LINK_UP (1 << 9) + +#define PCIE_ARCACHE_TRC 0x8050 +#define PCIE_AWCACHE_TRC 0x8054 +#define ARCACHE_SHAREABLE_CACHEABLE 0x3511 +#define AWCACHE_SHAREABLE_CACHEABLE 0x5311 + +#define LINK_SPEED_GEN_1 0x1 +#define LINK_SPEED_GEN_2 0x2 +#define LINK_SPEED_GEN_3 0x3 + +/** + * struct pcie_dw_mvebu - MVEBU DW PCIe controller state + * + * @ctrl_base: The base address of the register space + * @cfg_base: The base address of the configuration space + * @cfg_size: The size of the configuration space which is needed + * as it gets written into the PCIE_ATU_LIMIT register + * @first_busno: This driver supports multiple PCIe controllers. + * first_busno stores the bus number of the PCIe root-port + * number which may vary depending on the PCIe setup + * (PEX switches etc). + */ +struct pcie_dw_mvebu { + void *ctrl_base; + void *cfg_base; + fdt_size_t cfg_size; + int first_busno; +}; + +static int pcie_dw_get_link_speed(const void *regs_base) +{ + return (readl(regs_base + PCIE_LINK_STATUS_REG) & + PCIE_LINK_STATUS_SPEED_MASK) >> PCIE_LINK_STATUS_SPEED_OFF; +} + +static int pcie_dw_get_link_width(const void *regs_base) +{ + return (readl(regs_base + PCIE_LINK_STATUS_REG) & + PCIE_LINK_STATUS_WIDTH_MASK) >> PCIE_LINK_STATUS_WIDTH_OFF; +} + +/** + * set_cfg_address() - Configure the PCIe controller config space access + * + * @pcie: Pointer to the PCI controller state + * @d: PCI device to access + * @where: Offset in the configuration space + * + * Configures the PCIe controller to access the configuration space of + * a specific PCIe device and returns the address to use for this + * access. + * + * Return: Address that can be used to access the configation space + * of the requested device / offset + */ +static uintptr_t set_cfg_address(struct pcie_dw_mvebu *pcie, + pci_dev_t d, uint where) +{ + uintptr_t va_address; + + /* + * Region #0 is used for Outbound CFG space access. + * Direction = Outbound + * Region Index = 0 + */ + writel(0, pcie->ctrl_base + PCIE_ATU_VIEWPORT); + + if (PCI_BUS(d) == (pcie->first_busno + 1)) + /* For local bus, change TLP Type field to 4. */ + writel(PCIE_ATU_TYPE_CFG0, pcie->ctrl_base + PCIE_ATU_CR1); + else + /* Otherwise, change TLP Type field to 5. */ + writel(PCIE_ATU_TYPE_CFG1, pcie->ctrl_base + PCIE_ATU_CR1); + + if (PCI_BUS(d) == pcie->first_busno) { + /* Accessing root port configuration space. */ + va_address = (uintptr_t)pcie->ctrl_base; + } else { + writel(d << 8, pcie->ctrl_base + PCIE_ATU_LOWER_TARGET); + va_address = (uintptr_t)pcie->cfg_base; + } + + va_address += where & ~0x3; + + return va_address; +} + +/** + * pcie_dw_addr_valid() - Check for valid bus address + * + * @d: The PCI device to access + * @first_busno: Bus number of the PCIe controller root complex + * + * Return 1 (true) if the PCI device can be accessed by this controller. + * + * Return: 1 on valid, 0 on invalid + */ +static int pcie_dw_addr_valid(pci_dev_t d, int first_busno) +{ + if ((PCI_BUS(d) == first_busno) && (PCI_DEV(d) > 0)) + return 0; + if ((PCI_BUS(d) == first_busno + 1) && (PCI_DEV(d) > 0)) + return 0; + + return 1; +} + +/** + * pcie_dw_mvebu_read_config() - Read from configuration space + * + * @bus: Pointer to the PCI bus + * @bdf: Identifies the PCIe device to access + * @offset: The offset into the device's configuration space + * @valuep: A pointer at which to store the read value + * @size: Indicates the size of access to perform + * + * Read a value of size @size from offset @offset within the configuration + * space of the device identified by the bus, device & function numbers in @bdf + * on the PCI bus @bus. + * + * Return: 0 on success + */ +static int pcie_dw_mvebu_read_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong *valuep, + enum pci_size_t size) +{ + struct pcie_dw_mvebu *pcie = dev_get_priv(bus); + uintptr_t va_address; + ulong value; + + debug("PCIE CFG read: (b,d,f)=(%2d,%2d,%2d) ", + PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); + + if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) { + debug("- out of range\n"); + *valuep = pci_get_ff(size); + return 0; + } + + va_address = set_cfg_address(pcie, bdf, offset); + + value = readl(va_address); + + debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value); + *valuep = pci_conv_32_to_size(value, offset, size); + + return 0; +} + +/** + * pcie_dw_mvebu_write_config() - Write to configuration space + * + * @bus: Pointer to the PCI bus + * @bdf: Identifies the PCIe device to access + * @offset: The offset into the device's configuration space + * @value: The value to write + * @size: Indicates the size of access to perform + * + * Write the value @value of size @size from offset @offset within the + * configuration space of the device identified by the bus, device & function + * numbers in @bdf on the PCI bus @bus. + * + * Return: 0 on success + */ +static int pcie_dw_mvebu_write_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong value, + enum pci_size_t size) +{ + struct pcie_dw_mvebu *pcie = dev_get_priv(bus); + uintptr_t va_address; + ulong old; + + debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ", + PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); + debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value); + + if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) { + debug("- out of range\n"); + return 0; + } + + va_address = set_cfg_address(pcie, bdf, offset); + + old = readl(va_address); + value = pci_conv_size_to_32(old, value, offset, size); + writel(value, va_address); + + return 0; +} + +/** + * pcie_dw_configure() - Configure link capabilities and speed + * + * @regs_base: A pointer to the PCIe controller registers + * @cap_speed: The capabilities and speed to configure + * + * Configure the link capabilities and speed in the PCIe root complex. + */ +static void pcie_dw_configure(const void *regs_base, u32 cap_speed) +{ + /* + * TODO (shadi@marvell.com, sr@denx.de): + * Need to read the serdes speed from the dts and according to it + * configure the PCIe gen + */ + + /* Set link to GEN 3 */ + clrsetbits_le32(regs_base + PCIE_LINK_CTL_2, + TARGET_LINK_SPEED_MASK, cap_speed); + clrsetbits_le32(regs_base + PCIE_LINK_CAPABILITY, + TARGET_LINK_SPEED_MASK, cap_speed); + setbits_le32(regs_base + PCIE_GEN3_EQU_CTRL, GEN3_EQU_EVAL_2MS_DISABLE); +} + +/** + * is_link_up() - Return the link state + * + * @regs_base: A pointer to the PCIe controller registers + * + * Return: 1 (true) for active line and 0 (false) for no link + */ +static int is_link_up(const void *regs_base) +{ + u32 mask = PCIE_GLB_STS_RDLH_LINK_UP | PCIE_GLB_STS_PHY_LINK_UP; + u32 reg; + + reg = readl(regs_base + PCIE_GLOBAL_STATUS); + if ((reg & mask) == mask) + return 1; + + return 0; +} + +/** + * wait_link_up() - Wait for the link to come up + * + * @regs_base: A pointer to the PCIe controller registers + * + * Return: 1 (true) for active line and 0 (false) for no link (timeout) + */ +static int wait_link_up(const void *regs_base) +{ + unsigned long timeout; + + timeout = get_timer(0) + PCIE_LINK_UP_TIMEOUT_MS; + while (!is_link_up(regs_base)) { + if (get_timer(0) > timeout) + return 0; + }; + + return 1; +} + +/** + * pcie_dw_mvebu_pcie_link_up() - Configure the PCIe root port + * + * @regs_base: A pointer to the PCIe controller registers + * @cap_speed: The capabilities and speed to configure + * + * Configure the PCIe controller root complex depending on the + * requested link capabilities and speed. + * + * Return: 1 (true) for active line and 0 (false) for no link + */ +static int pcie_dw_mvebu_pcie_link_up(const void *regs_base, u32 cap_speed) +{ + if (!is_link_up(regs_base)) { + /* Disable LTSSM state machine to enable configuration */ + clrbits_le32(regs_base + PCIE_GLOBAL_CONTROL, + PCIE_APP_LTSSM_EN); + } + + clrsetbits_le32(regs_base + PCIE_GLOBAL_CONTROL, + PCIE_DEVICE_TYPE_MASK << PCIE_DEVICE_TYPE_OFFSET, + PCIE_DEVICE_TYPE_RC << PCIE_DEVICE_TYPE_OFFSET); + + /* Set the PCIe master AXI attributes */ + writel(ARCACHE_SHAREABLE_CACHEABLE, regs_base + PCIE_ARCACHE_TRC); + writel(AWCACHE_SHAREABLE_CACHEABLE, regs_base + PCIE_AWCACHE_TRC); + + /* DW pre link configurations */ + pcie_dw_configure(regs_base, cap_speed); + + if (!is_link_up(regs_base)) { + /* Configuration done. Start LTSSM */ + setbits_le32(regs_base + PCIE_GLOBAL_CONTROL, + PCIE_APP_LTSSM_EN); + } + + /* Check that link was established */ + if (!wait_link_up(regs_base)) + return 0; + + /* + * Link can be established in Gen 1. still need to wait + * till MAC nagaotiation is completed + */ + udelay(100); + + return 1; +} + +/** + * pcie_dw_regions_setup() - iATU region setup + * + * @pcie: Pointer to the PCI controller state + * + * Configure the iATU regions in the PCIe controller for outbound access. + */ +static void pcie_dw_regions_setup(struct pcie_dw_mvebu *pcie) +{ + /* + * Region #0 is used for Outbound CFG space access. + * Direction = Outbound + * Region Index = 0 + */ + writel(0, pcie->ctrl_base + PCIE_ATU_VIEWPORT); + + writel((u32)(uintptr_t)pcie->cfg_base, pcie->ctrl_base + + PCIE_ATU_LOWER_BASE); + writel(0, pcie->ctrl_base + PCIE_ATU_UPPER_BASE); + writel((u32)(uintptr_t)pcie->cfg_base + pcie->cfg_size, + pcie->ctrl_base + PCIE_ATU_LIMIT); + + writel(0, pcie->ctrl_base + PCIE_ATU_LOWER_TARGET); + writel(0, pcie->ctrl_base + PCIE_ATU_UPPER_TARGET); + writel(PCIE_ATU_TYPE_CFG0, pcie->ctrl_base + PCIE_ATU_CR1); + writel(PCIE_ATU_ENABLE, pcie->ctrl_base + PCIE_ATU_CR2); +} + +/** + * pcie_dw_set_host_bars() - Configure the host BARs + * + * @regs_base: A pointer to the PCIe controller registers + * + * Configure the host BARs of the PCIe controller root port so that + * PCI(e) devices may access the system memory. + */ +static void pcie_dw_set_host_bars(const void *regs_base) +{ + u32 size = gd->ram_size; + u64 max_size; + u32 reg; + u32 bar0; + + /* Verify the maximal BAR size */ + reg = readl(regs_base + RESIZABLE_BAR_CAP); + max_size = 1ULL << (5 + (reg + (1 << 4))); + + if (size > max_size) { + size = max_size; + printf("Warning: PCIe BARs can't map all DRAM space\n"); + } + + /* Set the BAR base and size towards DDR */ + bar0 = CONFIG_SYS_SDRAM_BASE & ~0xf; + bar0 |= PCI_BASE_ADDRESS_MEM_TYPE_32; + writel(CONFIG_SYS_SDRAM_BASE, regs_base + PCIE_CONFIG_BAR0); + + reg = ((size >> 20) - 1) << 12; + writel(size, regs_base + RESIZABLE_BAR_CTL0); +} + +/** + * pcie_dw_mvebu_probe() - Probe the PCIe bus for active link + * + * @dev: A pointer to the device being operated on + * + * Probe for an active link on the PCIe bus and configure the controller + * to enable this port. + * + * Return: 0 on success, else -ENODEV + */ +static int pcie_dw_mvebu_probe(struct udevice *dev) +{ + struct pcie_dw_mvebu *pcie = dev_get_priv(dev); + struct udevice *ctlr = pci_get_controller(dev); + struct pci_controller *hose = dev_get_uclass_priv(ctlr); + + pcie->first_busno = dev->seq; + + /* Don't register host if link is down */ + if (!pcie_dw_mvebu_pcie_link_up(pcie->ctrl_base, LINK_SPEED_GEN_3)) { + printf("PCIE-%d: Link down\n", dev->seq); + return -ENODEV; + } + + printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n", dev->seq, + pcie_dw_get_link_speed(pcie->ctrl_base), + pcie_dw_get_link_width(pcie->ctrl_base), hose->first_busno); + + pcie_dw_regions_setup(pcie); + + /* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI */ + clrsetbits_le32(pcie->ctrl_base + PCI_CLASS_REVISION, + 0xffff << 16, PCI_CLASS_BRIDGE_PCI << 16); + + pcie_dw_set_host_bars(pcie->ctrl_base); + + return 0; +} + +/** + * pcie_dw_mvebu_ofdata_to_platdata() - Translate from DT to device state + * + * @dev: A pointer to the device being operated on + * + * Translate relevant data from the device tree pertaining to device @dev into + * state that the driver will later make use of. This state is stored in the + * device's private data structure. + * + * Return: 0 on success, else -EINVAL + */ +static int pcie_dw_mvebu_ofdata_to_platdata(struct udevice *dev) +{ + struct pcie_dw_mvebu *pcie = dev_get_priv(dev); + + /* Get the controller base address */ + pcie->ctrl_base = (void *)dev_get_addr_index(dev, 0); + if ((fdt_addr_t)pcie->ctrl_base == FDT_ADDR_T_NONE) + return -EINVAL; + + /* Get the config space base address and size */ + pcie->cfg_base = (void *)dev_get_addr_size_index(dev, 1, + &pcie->cfg_size); + if ((fdt_addr_t)pcie->cfg_base == FDT_ADDR_T_NONE) + return -EINVAL; + + return 0; +} + +static const struct dm_pci_ops pcie_dw_mvebu_ops = { + .read_config = pcie_dw_mvebu_read_config, + .write_config = pcie_dw_mvebu_write_config, +}; + +static const struct udevice_id pcie_dw_mvebu_ids[] = { + { .compatible = "marvell,armada8k-pcie" }, + { } +}; + +U_BOOT_DRIVER(pcie_dw_mvebu) = { + .name = "pcie_dw_mvebu", + .id = UCLASS_PCI, + .of_match = pcie_dw_mvebu_ids, + .ops = &pcie_dw_mvebu_ops, + .ofdata_to_platdata = pcie_dw_mvebu_ofdata_to_platdata, + .probe = pcie_dw_mvebu_probe, + .priv_auto_alloc_size = sizeof(struct pcie_dw_mvebu), +}; diff --git a/drivers/phy/marvell/comphy.h b/drivers/phy/marvell/comphy.h index df5b7d507e..0a15692579 100644 --- a/drivers/phy/marvell/comphy.h +++ b/drivers/phy/marvell/comphy.h @@ -69,7 +69,7 @@ (0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET) #define MAX_LANE_OPTIONS 10 -#define MAX_UTMI_PHY_COUNT 2 +#define MAX_UTMI_PHY_COUNT 3 struct comphy_mux_options { u32 type; diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c index 651397d816..bc2508bb7e 100644 --- a/drivers/phy/marvell/comphy_core.c +++ b/drivers/phy/marvell/comphy_core.c @@ -112,6 +112,7 @@ static int comphy_probe(struct udevice *dev) struct comphy_map comphy_map_data[MAX_LANE_OPTIONS]; int subnode; int lane; + int last_idx = 0; /* Save base addresses for later use */ chip_cfg->comphy_base_addr = (void *)dev_get_addr_index(dev, 0); @@ -178,10 +179,20 @@ static int comphy_probe(struct udevice *dev) /* PHY power UP sequence */ chip_cfg->ptr_comphy_chip_init(chip_cfg, comphy_map_data); /* PHY print SerDes status */ + if (of_machine_is_compatible("marvell,armada8040")) + printf("Comphy chip #%d:\n", chip_cfg->comphy_index); comphy_print(chip_cfg, comphy_map_data); - /* Initialize dedicated PHYs (not muxed SerDes lanes) */ - comphy_dedicated_phys_init(); + /* + * Only run the dedicated PHY init code once, in the last PHY init call + */ + if (of_machine_is_compatible("marvell,armada8040")) + last_idx = 1; + + if (chip_cfg->comphy_index == last_idx) { + /* Initialize dedicated PHYs (not muxed SerDes lanes) */ + comphy_dedicated_phys_init(); + } return 0; } diff --git a/include/configs/mvebu_db-88f7040.h b/include/configs/mvebu_armada-8k.h index 6feb8d7eca..8ab5bbee7d 100644 --- a/include/configs/mvebu_db-88f7040.h +++ b/include/configs/mvebu_armada-8k.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#ifndef _CONFIG_MVEBU_DB_88F7040_H -#define _CONFIG_MVEBU_DB_88F7040_H +#ifndef _CONFIG_MVEBU_ARMADA_8K_H +#define _CONFIG_MVEBU_ARMADA_8K_H /* * High Level Configuration Options (easy to change) @@ -128,4 +128,12 @@ #define CONFIG_CMD_PART #define CONFIG_PARTITION_UUIDS -#endif /* _CONFIG_MVEBU_DB_88F7040_H */ +/* + * PCI configuration + */ +#ifdef CONFIG_PCIE_DW_MVEBU +#define CONFIG_E1000 +#define CONFIG_CMD_PCI +#endif + +#endif /* _CONFIG_MVEBU_ARMADA_8K_H */ |