diff options
75 files changed, 4047 insertions, 719 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 607bc9c..9ab5428 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -93,12 +93,14 @@ F: arch/arm/include/asm/arch-mx*/ F: arch/arm/include/asm/arch-vf610/ F: arch/arm/include/asm/imx-common/ -ARM MARVELL KIRKWOOD +ARM MARVELL KIRKWOOD ARMADA-XP ARMADA-38X M: Prafulla Wadaskar <prafulla@marvell.com> M: Luka Perkov <luka.perkov@sartura.hr> +M: Stefan Roese <sr@denx.de> S: Maintained T: git git://git.denx.de/u-boot-marvell.git F: arch/arm/mach-kirkwood/ +F: arch/arm/mach-mvebu/ ARM MARVELL PXA M: Marek Vasut <marex@denx.de> @@ -915,18 +915,8 @@ MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \ u-boot.img u-boot.kwb u-boot.pbl: u-boot.bin FORCE $(call if_changed,mkimage) -# If the kwboot xmodem protocol is used, to boot U-Boot on the MVEBU -# SoC's, the SPL U-Boot returns to the BootROM after it completes -# the SDRAM setup. The BootROM expects no U-Boot header in the main -# U-Boot image. So we need to combine SPL and u-boot.bin instead of -# u-boot.img in this case. -ifdef CONFIG_MVEBU_BOOTROM_UARTBOOT -u-boot-spl.kwb: u-boot-dtb.bin spl/u-boot-spl.bin FORCE - $(call if_changed,mkimage) -else u-boot-spl.kwb: u-boot-dtb.img spl/u-boot-spl.bin FORCE $(call if_changed,mkimage) -endif MKIMAGEFLAGS_u-boot-dtb.img = $(MKIMAGEFLAGS_u-boot.img) @@ -5118,14 +5118,11 @@ If the system board that you have is not listed, then you will need to port U-Boot to your hardware platform. To do this, follow these steps: -1. Add a new configuration option for your board to the toplevel - "boards.cfg" file, using the existing entries as examples. - Follow the instructions there to keep the boards in order. -2. Create a new directory to hold your board specific code. Add any +1. Create a new directory to hold your board specific code. Add any files you need. In your board directory, you will need at least - the "Makefile", a "<board>.c", "flash.c" and "u-boot.lds". -3. Create a new configuration file "include/configs/<board>.h" for - your board + the "Makefile" and a "<board>.c". +2. Create a new configuration file "include/configs/<board>.h" for + your board. 3. If you're porting U-Boot to a new CPU, then also create a new directory to hold your CPU specific code. Add any files you need. 4. Run "make <board>_defconfig" with your new name. diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 52b300d..dd9cac9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -117,8 +117,14 @@ config ARCH_MVEBU select OF_CONTROL select OF_SEPARATE select DM + select DM_ETH 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" @@ -770,8 +776,6 @@ source "board/BuR/kwb/Kconfig" source "board/BuR/tseries/Kconfig" source "board/CarMediaLab/flea3/Kconfig" source "board/Marvell/aspenite/Kconfig" -source "board/Marvell/db-88f6820-gp/Kconfig" -source "board/Marvell/db-mv784mp-gp/Kconfig" source "board/Marvell/gplugd/Kconfig" source "board/armadeus/apf27/Kconfig" source "board/armltd/vexpress/Kconfig" @@ -810,7 +814,6 @@ source "board/h2200/Kconfig" source "board/hisilicon/hikey/Kconfig" source "board/imx31_phycore/Kconfig" source "board/isee/igep0033/Kconfig" -source "board/maxbcm/Kconfig" source "board/mpl/vcma9/Kconfig" source "board/olimex/mx23_olinuxino/Kconfig" source "board/phytec/pcm051/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 18283d1..3d15673 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -49,7 +49,7 @@ machine-$(CONFIG_ARCH_HIGHBANK) += highbank machine-$(CONFIG_ARCH_KEYSTONE) += keystone # TODO: rename CONFIG_KIRKWOOD -> CONFIG_ARCH_KIRKWOOD machine-$(CONFIG_KIRKWOOD) += kirkwood -machine-$(CONFIG_ARMADA_XP) += mvebu +machine-$(CONFIG_ARCH_MVEBU) += mvebu # TODO: rename CONFIG_TEGRA -> CONFIG_ARCH_TEGRA # TODO: rename CONFIG_ORION5X -> CONFIG_ARCH_ORION5X machine-$(CONFIG_ORION5X) += orion5x diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 0bcd316..64b8371 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -48,8 +48,11 @@ dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \ tegra210-p2571.dtb dtb-$(CONFIG_ARCH_MVEBU) += \ + armada-388-clearfog.dtb \ armada-388-gp.dtb \ - armada-xp-gp.dtb + armada-xp-gp.dtb \ + armada-xp-maxbcm.dtb \ + armada-xp-synology-ds414.dtb dtb-$(CONFIG_ARCH_UNIPHIER) += \ uniphier-ph1-ld4-ref.dtb \ diff --git a/arch/arm/dts/armada-370-xp.dtsi b/arch/arm/dts/armada-370-xp.dtsi index a718866..0b2a78d 100644 --- a/arch/arm/dts/armada-370-xp.dtsi +++ b/arch/arm/dts/armada-370-xp.dtsi @@ -141,6 +141,7 @@ #address-cells = <1>; #size-cells = <1>; ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>; + u-boot,dm-pre-reloc; rtc@10300 { compatible = "marvell,orion-rtc"; diff --git a/arch/arm/dts/armada-388-clearfog.dts b/arch/arm/dts/armada-388-clearfog.dts new file mode 100644 index 0000000..b2dfd56 --- /dev/null +++ b/arch/arm/dts/armada-388-clearfog.dts @@ -0,0 +1,509 @@ +/* + * Device Tree file for SolidRun Clearfog revision A1 rev 2.0 (88F6828) + * + * Copyright (C) 2015 Russell King + * + * This board is in development; the contents of this file work with + * the A1 rev 2.0 of the board, which does not represent final + * production board. Things will change, don't expect this file to + * remain compatible info the future. + * + * 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 + * version 2 as published by the Free Software Foundation. + * + * 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 <dt-bindings/input/input.h> +#include <dt-bindings/gpio/gpio.h> +#include "armada-388.dtsi" + +/ { + model = "SolidRun Clearfog A1"; + compatible = "solidrun,clearfog-a1", "marvell,armada388", + "marvell,armada385", "marvell,armada380"; + + aliases { + /* So that mvebu u-boot can update the MAC addresses */ + ethernet1 = ð0; + ethernet2 = ð1; + ethernet3 = ð2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x10000000>; /* 256 MB */ + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + soc { + ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 + MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; + + internal-regs { + ethernet@30000 { + mac-address = [00 50 43 02 02 02]; + phy-mode = "sgmii"; + status = "okay"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + ethernet@34000 { + mac-address = [00 50 43 02 02 03]; + managed = "in-band-status"; + phy-mode = "sgmii"; + status = "okay"; + }; + + ethernet@70000 { + mac-address = [00 50 43 02 02 01]; + pinctrl-0 = <&ge0_rgmii_pins>; + pinctrl-names = "default"; + phy = <&phy_dedicated>; + phy-mode = "rgmii-id"; + status = "okay"; + }; + + i2c@11000 { + /* Is there anything on this? */ + clock-frequency = <100000>; + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + status = "okay"; + + /* + * PCA9655 GPIO expander, up to 1MHz clock. + * 0-CON3 CLKREQ# + * 1-CON3 PERST# + * 2-CON2 PERST# + * 3-CON3 W_DISABLE + * 4-CON2 CLKREQ# + * 5-USB3 overcurrent + * 6-USB3 power + * 7-CON2 W_DISABLE + * 8-JP4 P1 + * 9-JP4 P4 + * 10-JP4 P5 + * 11-m.2 DEVSLP + * 12-SFP_LOS + * 13-SFP_TX_FAULT + * 14-SFP_TX_DISABLE + * 15-SFP_MOD_DEF0 + */ + expander0: gpio-expander@20 { + /* + * This is how it should be: + * compatible = "onnn,pca9655", + * "nxp,pca9555"; + * but you can't do this because of + * the way I2C works. + */ + compatible = "nxp,pca9555"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x20>; + + pcie1_0_clkreq { + gpio-hog; + gpios = <0 GPIO_ACTIVE_LOW>; + input; + line-name = "pcie1.0-clkreq"; + }; + pcie1_0_w_disable { + gpio-hog; + gpios = <3 GPIO_ACTIVE_LOW>; + output-low; + line-name = "pcie1.0-w-disable"; + }; + pcie2_0_clkreq { + gpio-hog; + gpios = <4 GPIO_ACTIVE_LOW>; + input; + line-name = "pcie2.0-clkreq"; + }; + pcie2_0_w_disable { + gpio-hog; + gpios = <7 GPIO_ACTIVE_LOW>; + output-low; + line-name = "pcie2.0-w-disable"; + }; + usb3_ilimit { + gpio-hog; + gpios = <5 GPIO_ACTIVE_LOW>; + input; + line-name = "usb3-current-limit"; + }; + usb3_power { + gpio-hog; + gpios = <6 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "usb3-power"; + }; + m2_devslp { + gpio-hog; + gpios = <11 GPIO_ACTIVE_HIGH>; + output-low; + line-name = "m.2 devslp"; + }; + }; + + /* The MCP3021 is 100kHz clock only */ + mikrobus_adc: mcp3021@4c { + compatible = "microchip,mcp3021"; + reg = <0x4c>; + }; + + /* Also something at 0x64 */ + }; + + i2c@11100 { + /* + * Routed to SFP, mikrobus, and PCIe. + * SFP limits this to 100kHz, and requires + * an AT24C01A/02/04 with address pins tied + * low, which takes addresses 0x50 and 0x51. + * Mikrobus doesn't specify beyond an I2C + * bus being present. + * PCIe uses ARP to assign addresses, or + * 0x63-0x64. + */ + clock-frequency = <100000>; + pinctrl-0 = <&clearfog_i2c1_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + mdio@72004 { + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + + phy_dedicated: ethernet-phy@0 { + /* + * Annoyingly, the marvell phy driver + * configures the LED register, rather + * than preserving reset-loaded setting. + * We undo that rubbish here. + */ + marvell,reg-init = <3 16 0 0x101e>; + reg = <0>; + }; + }; + + pinctrl@18000 { + clearfog_dsa0_clk_pins: clearfog-dsa0-clk-pins { + marvell,pins = "mpp46"; + marvell,function = "ref"; + }; + clearfog_dsa0_pins: clearfog-dsa0-pins { + marvell,pins = "mpp23", "mpp41"; + marvell,function = "gpio"; + }; + clearfog_i2c1_pins: i2c1-pins { + /* SFP, PCIe, mSATA, mikrobus */ + marvell,pins = "mpp26", "mpp27"; + marvell,function = "i2c1"; + }; + clearfog_sdhci_cd_pins: clearfog-sdhci-cd-pins { + marvell,pins = "mpp20"; + marvell,function = "gpio"; + }; + clearfog_sdhci_pins: clearfog-sdhci-pins { + marvell,pins = "mpp21", "mpp28", + "mpp37", "mpp38", + "mpp39", "mpp40"; + marvell,function = "sd0"; + }; + clearfog_spi1_cs_pins: spi1-cs-pins { + marvell,pins = "mpp55"; + marvell,function = "spi1"; + }; + mikro_pins: mikro-pins { + /* int: mpp22 rst: mpp29 */ + marvell,pins = "mpp22", "mpp29"; + marvell,function = "gpio"; + }; + mikro_spi_pins: mikro-spi-pins { + marvell,pins = "mpp43"; + marvell,function = "spi1"; + }; + mikro_uart_pins: mikro-uart-pins { + marvell,pins = "mpp24", "mpp25"; + marvell,function = "ua1"; + }; + rear_button_pins: rear-button-pins { + marvell,pins = "mpp34"; + marvell,function = "gpio"; + }; + }; + + rtc@a3800 { + /* + * If the rtc doesn't work, run "date reset" + * twice in u-boot. + */ + status = "okay"; + }; + + sata@a8000 { + /* pinctrl? */ + status = "okay"; + }; + + sata@e0000 { + /* pinctrl? */ + status = "okay"; + }; + + sdhci@d8000 { + bus-width = <4>; + cd-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; + no-1-8-v; + pinctrl-0 = <&clearfog_sdhci_pins + &clearfog_sdhci_cd_pins>; + pinctrl-names = "default"; + status = "okay"; + vmmc = <®_3p3v>; + wp-inverted; + }; + + serial@12000 { + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; + status = "okay"; + u-boot,dm-pre-reloc; + }; + + serial@12100 { + /* mikrobus uart */ + pinctrl-0 = <&mikro_uart_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + spi@10680 { + /* + * We don't seem to have the W25Q32 on the + * A1 Rev 2.0 boards, so disable SPI. + * CS0: W25Q32 (doesn't appear to be present) + * CS1: + * CS2: mikrobus + */ + pinctrl-0 = <&spi1_pins &clearfog_spi1_cs_pins &mikro_spi_pins>; + pinctrl-names = "default"; + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "w25q32", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <3000000>; + status = "disabled"; + }; + }; + + usb3@f8000 { + status = "okay"; + }; + }; + + pcie-controller { + status = "okay"; + /* + * The two PCIe units are accessible through + * the mini-PCIe connectors on the board. + */ + pcie@2,0 { + /* Port 1, Lane 0. CONN3, nearest power. */ + reset-gpios = <&expander0 1 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + pcie@3,0 { + /* Port 2, Lane 0. CONN2, nearest CPU. */ + reset-gpios = <&expander0 2 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + }; + }; + + sfp: sfp { + compatible = "sff,sfp"; + i2c-bus = <&i2c1>; + los-gpio = <&expander0 12 GPIO_ACTIVE_HIGH>; + moddef0-gpio = <&expander0 15 GPIO_ACTIVE_LOW>; + sfp,ethernet = <ð2>; + tx-disable-gpio = <&expander0 14 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&expander0 13 GPIO_ACTIVE_HIGH>; + }; + + dsa@0 { + compatible = "marvell,dsa"; + dsa,ethernet = <ð1>; + dsa,mii-bus = <&mdio>; + pinctrl-0 = <&clearfog_dsa0_clk_pins &clearfog_dsa0_pins>; + pinctrl-names = "default"; + #address-cells = <2>; + #size-cells = <0>; + + switch@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4 0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@4 { + reg = <4>; + label = "lan5"; + }; + + port@5 { + reg = <5>; + label = "cpu"; + }; + + port@6 { + /* 88E1512 external phy */ + reg = <6>; + label = "lan6"; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-0 = <&rear_button_pins>; + pinctrl-names = "default"; + + button_0 { + /* The rear SW3 button */ + label = "Rear Button"; + gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; + linux,can-disable; + linux,code = <BTN_0>; + }; + }; +}; + +/* ++#define A38x_CUSTOMER_BOARD_1_MPP16_23 0x00400011 +MPP18: gpio ? (pca9655 int?) +MPP19: gpio ? (clkreq?) +MPP20: gpio ? (sd0 detect) +MPP21: sd0:cmd x sd0 +MPP22: gpio x mikro int +MPP23: gpio x switch irq ++#define A38x_CUSTOMER_BOARD_1_MPP24_31 0x22043333 +MPP24: ua1:rxd x mikro rx +MPP25: ua1:txd x mikro tx +MPP26: i2c1:sck x mikro sck +MPP27: i2c1:sda x mikro sda +MPP28: sd0:clk x sd0 +MPP29: gpio x mikro rst +MPP30: ge1:txd2 ? (config) +MPP31: ge1:txd3 ? (config) ++#define A38x_CUSTOMER_BOARD_1_MPP32_39 0x44400002 +MPP32: ge1:txctl ? (unused) +MPP33: gpio ? (pic_com0) +MPP34: gpio x rear button (pic_com1) +MPP35: gpio ? (pic_com2) +MPP36: gpio ? (unused) +MPP37: sd0:d3 x sd0 +MPP38: sd0:d0 x sd0 +MPP39: sd0:d1 x sd0 ++#define A38x_CUSTOMER_BOARD_1_MPP40_47 0x41144004 +MPP40: sd0:d2 x sd0 +MPP41: gpio x switch reset +MPP42: gpio ? sw1-1 +MPP43: spi1:cs2 x mikro cs +MPP44: sata3:prsnt ? (unused) +MPP45: ref:clk_out0 ? +MPP46: ref:clk_out1 x switch clk +MPP47: 4 ? (unused) ++#define A38x_CUSTOMER_BOARD_1_MPP48_55 0x40333333 +MPP48: tdm:pclk +MPP49: tdm:fsync +MPP50: tdm:drx +MPP51: tdm:dtx +MPP52: tdm:int +MPP53: tdm:rst +MPP54: gpio ? (pwm) +MPP55: spi1:cs1 x slic ++#define A38x_CUSTOMER_BOARD_1_MPP56_63 0x00004444 +MPP56: spi1:mosi x mikro mosi +MPP57: spi1:sck x mikro sck +MPP58: spi1:miso x mikro miso +MPP59: spi1:cs0 x w25q32 +*/ diff --git a/arch/arm/dts/armada-388-gp.dts b/arch/arm/dts/armada-388-gp.dts index fd4f6fd..7bc878f 100644 --- a/arch/arm/dts/armada-388-gp.dts +++ b/arch/arm/dts/armada-388-gp.dts @@ -51,6 +51,12 @@ stdout-path = "serial0:115200n8"; }; + aliases { + ethernet0 = ð0; + ethernet1 = ð1; + spi0 = &spi0; + }; + memory { device_type = "memory"; reg = <0x00000000 0x80000000>; /* 2 GB */ @@ -65,8 +71,10 @@ pinctrl-names = "default"; pinctrl-0 = <&spi0_pins>; status = "okay"; + u-boot,dm-pre-reloc; spi-flash@0 { + u-boot,dm-pre-reloc; #address-cells = <1>; #size-cells = <1>; compatible = "st,m25p128", "jedec,spi-nor"; @@ -122,6 +130,7 @@ pinctrl-names = "default"; pinctrl-0 = <&uart0_pins>; status = "okay"; + u-boot,dm-pre-reloc; }; /* GE1 CON15 */ diff --git a/arch/arm/dts/armada-38x.dtsi b/arch/arm/dts/armada-38x.dtsi index 04ecfe6..dc8a1a6 100644 --- a/arch/arm/dts/armada-38x.dtsi +++ b/arch/arm/dts/armada-38x.dtsi @@ -70,6 +70,7 @@ soc { compatible = "marvell,armada380-mbus", "simple-bus"; + u-boot,dm-pre-reloc; #address-cells = <2>; #size-cells = <1>; controller = <&mbusc>; @@ -134,6 +135,7 @@ internal-regs { compatible = "simple-bus"; + u-boot,dm-pre-reloc; #address-cells = <1>; #size-cells = <1>; ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>; diff --git a/arch/arm/dts/armada-xp-gp.dts b/arch/arm/dts/armada-xp-gp.dts index bf724ca..27799d1 100644 --- a/arch/arm/dts/armada-xp-gp.dts +++ b/arch/arm/dts/armada-xp-gp.dts @@ -68,6 +68,10 @@ stdout-path = "serial0:115200n8"; }; + aliases { + spi0 = &spi0; + }; + memory { device_type = "memory"; /* @@ -148,6 +152,7 @@ internal-regs { serial@12000 { status = "okay"; + u-boot,dm-pre-reloc; }; serial@12100 { status = "okay"; @@ -223,8 +228,10 @@ spi0: spi@10600 { status = "okay"; + u-boot,dm-pre-reloc; spi-flash@0 { + u-boot,dm-pre-reloc; #address-cells = <1>; #size-cells = <1>; compatible = "n25q128a13", "jedec,spi-nor"; diff --git a/arch/arm/dts/armada-xp-maxbcm.dts b/arch/arm/dts/armada-xp-maxbcm.dts new file mode 100644 index 0000000..d7d7f65 --- /dev/null +++ b/arch/arm/dts/armada-xp-maxbcm.dts @@ -0,0 +1,249 @@ +/* + * Device Tree file for Marvell Armada XP maxbcm board + * + * Copyright (C) 2013-2014 Marvell + * + * Lior Amsalem <alior@marvell.com> + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * Thomas Petazzoni <thomas.petazzoni@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. + * + * Note: this Device Tree assumes that the bootloader has remapped the + * internal registers to 0xf1000000 (instead of the default + * 0xd0000000). The 0xf1000000 is the default used by the recent, + * DT-capable, U-Boot bootloaders provided by Marvell. Some earlier + * boards were delivered with an older version of the bootloader that + * left internal registers mapped at 0xd0000000. If you are in this + * situation, you should either update your bootloader (preferred + * solution) or the below Device Tree should be adjusted. + */ + +/dts-v1/; +#include <dt-bindings/gpio/gpio.h> +#include "armada-xp-mv78460.dtsi" + +/ { + model = "Marvell Armada XP MAXBCM"; + compatible = "marvell,axp-gp", "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + spi0 = &spi0; + }; + + memory { + device_type = "memory"; + /* + * 8 GB of plug-in RAM modules by default.The amount + * of memory available can be changed by the + * bootloader according the size of the module + * actually plugged. However, memory between + * 0xF0000000 to 0xFFFFFFFF cannot be used, as it is + * the address range used for I/O (internal registers, + * MBus windows). + */ + reg = <0x00000000 0x00000000 0x00000000 0xf0000000>, + <0x00000001 0x00000000 0x00000001 0x00000000>; + }; + + cpus { + pm_pic { + ctrl-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>, + <&gpio0 17 GPIO_ACTIVE_LOW>, + <&gpio0 18 GPIO_ACTIVE_LOW>; + }; + }; + + soc { + ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 + MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000>; + + devbus-bootcs { + status = "okay"; + + /* Device Bus parameters are required */ + + /* Read parameters */ + devbus,bus-width = <16>; + devbus,turn-off-ps = <60000>; + devbus,badr-skew-ps = <0>; + devbus,acc-first-ps = <124000>; + devbus,acc-next-ps = <248000>; + devbus,rd-setup-ps = <0>; + devbus,rd-hold-ps = <0>; + + /* Write parameters */ + devbus,sync-enable = <0>; + devbus,wr-high-ps = <60000>; + devbus,wr-low-ps = <60000>; + devbus,ale-wr-ps = <60000>; + + /* NOR 16 MiB */ + nor@0 { + compatible = "cfi-flash"; + reg = <0 0x1000000>; + bank-width = <2>; + }; + }; + + pcie-controller { + status = "okay"; + + /* + * The 3 slots are physically present as + * standard PCIe slots on the board. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + pcie@9,0 { + /* Port 2, Lane 0 */ + status = "okay"; + }; + pcie@10,0 { + /* Port 3, Lane 0 */ + status = "okay"; + }; + }; + + internal-regs { + serial@12000 { + status = "okay"; + u-boot,dm-pre-reloc; + }; + serial@12100 { + status = "okay"; + }; + serial@12200 { + status = "okay"; + }; + serial@12300 { + status = "okay"; + }; + pinctrl { + pinctrl-0 = <&pic_pins>; + pinctrl-names = "default"; + pic_pins: pic-pins-0 { + marvell,pins = "mpp16", "mpp17", + "mpp18"; + marvell,function = "gpio"; + }; + }; + sata@a0000 { + nr-ports = <2>; + status = "okay"; + }; + + mdio { + phy0: ethernet-phy@0 { + reg = <0>; + }; + + phy1: ethernet-phy@1 { + reg = <1>; + }; + + phy2: ethernet-phy@2 { + reg = <2>; + }; + + phy3: ethernet-phy@3 { + reg = <3>; + }; + }; + + ethernet@70000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "sgmii"; + }; + ethernet@74000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "sgmii"; + }; + ethernet@30000 { + status = "okay"; + phy = <&phy2>; + phy-mode = "sgmii"; + }; + ethernet@34000 { + status = "okay"; + phy = <&phy3>; + phy-mode = "sgmii"; + }; + + /* Front-side USB slot */ + usb@50000 { + status = "okay"; + }; + + /* Back-side USB slot */ + usb@51000 { + status = "okay"; + }; + + spi0: spi@10600 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q128a13", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; + }; + }; + + nand@d0000 { + status = "okay"; + num-cs = <1>; + marvell,nand-keep-config; + marvell,nand-enable-arbiter; + nand-on-flash-bbt; + }; + }; + }; +}; diff --git a/arch/arm/dts/armada-xp-synology-ds414.dts b/arch/arm/dts/armada-xp-synology-ds414.dts new file mode 100644 index 0000000..0a60ddf --- /dev/null +++ b/arch/arm/dts/armada-xp-synology-ds414.dts @@ -0,0 +1,337 @@ +/* + * Device Tree file for Synology DS414 + * + * Copyright (C) 2014, Arnaud EBALARD <arno@natisbad.org> + * + * This program 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. + * + * Note: this Device Tree assumes that the bootloader has remapped the + * internal registers to 0xf1000000 (instead of the old 0xd0000000). + * The 0xf1000000 is the default used by the recent, DT-capable, U-Boot + * bootloaders provided by Marvell. It is used in recent versions of + * DSM software provided by Synology. Nonetheless, some earlier boards + * were delivered with an older version of u-boot that left internal + * registers mapped at 0xd0000000. If you have such a device you will + * not be able to directly boot a kernel based on this Device Tree. In + * that case, the preferred solution is to update your bootloader (e.g. + * by upgrading to latest version of DSM, or building a new one and + * installing it from u-boot prompt) or adjust the Devive Tree + * (s/0xf1000000/0xd0000000/ in 'ranges' below). + */ + +/dts-v1/; + +#include <dt-bindings/input/input.h> +#include <dt-bindings/gpio/gpio.h> +#include "armada-xp-mv78230.dtsi" + +/ { + model = "Synology DS414"; + compatible = "synology,ds414", "marvell,armadaxp-mv78230", + "marvell,armadaxp", "marvell,armada-370-xp"; + + chosen { + bootargs = "console=ttyS0,115200 earlyprintk"; + stdout-path = &uart0; + }; + + aliases { + spi0 = &spi0; + }; + + memory { + device_type = "memory"; + reg = <0 0x00000000 0 0x40000000>; /* 1GB */ + }; + + soc { + ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>; + + pcie-controller { + status = "okay"; + + /* + * Connected to Marvell 88SX7042 SATA-II controller + * handling the four disks. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + + /* + * Connected to EtronTech EJ168A XHCI controller + * providing the two rear USB 3.0 ports. + */ + pcie@5,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; + }; + + internal-regs { + + /* RTC is provided by Seiko S-35390A below */ + rtc@10300 { + status = "disabled"; + }; + + spi0: spi@10600 { + status = "okay"; + u-boot,dm-pre-reloc; + + spi-flash@0 { + u-boot,dm-pre-reloc; + #address-cells = <1>; + #size-cells = <1>; + compatible = "micron,n25q064"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <20000000>; + + /* + * Warning! + * + * Synology u-boot uses its compiled-in environment + * and it seems Synology did not care to change u-boot + * default configuration in order to allow saving a + * modified environment at a sensible location. So, + * if you do a 'saveenv' under u-boot, your modified + * environment will be saved at 1MB after the start + * of the flash, i.e. in the middle of the uImage. + * For that reason, it is strongly advised not to + * change the default environment, unless you know + * what you are doing. + */ + partition@00000000 { /* u-boot */ + label = "RedBoot"; + reg = <0x00000000 0x000d0000>; /* 832KB */ + }; + + partition@000c0000 { /* uImage */ + label = "zImage"; + reg = <0x000d0000 0x002d0000>; /* 2880KB */ + }; + + partition@003a0000 { /* uInitramfs */ + label = "rd.gz"; + reg = <0x003a0000 0x00430000>; /* 4250KB */ + }; + + partition@007d0000 { /* MAC address and serial number */ + label = "vendor"; + reg = <0x007d0000 0x00010000>; /* 64KB */ + }; + + partition@007e0000 { + label = "RedBoot config"; + reg = <0x007e0000 0x00010000>; /* 64KB */ + }; + + partition@007f0000 { + label = "FIS directory"; + reg = <0x007f0000 0x00010000>; /* 64KB */ + }; + }; + }; + + i2c@11000 { + clock-frequency = <400000>; + status = "okay"; + + s35390a: s35390a@30 { + compatible = "sii,s35390a"; + reg = <0x30>; + }; + }; + + /* Connected to a header on device's PCB. This + * provides the main console for the device. + * + * Warning: the device may not boot with a 3.3V + * USB-serial converter connected when the power + * button is pressed. The converter needs to be + * connected a few seconds after pressing the + * power button. This is possibly due to UART0_TXD + * pin being sampled at reset (bit 0 of SAR). + */ + serial@12000 { + status = "okay"; + u-boot,dm-pre-reloc; + }; + + /* Connected to a Microchip PIC16F883 for power control */ + serial@12100 { + status = "okay"; + }; + + poweroff@12100 { + compatible = "synology,power-off"; + reg = <0x12100 0x100>; + clocks = <&coreclk 0>; + }; + + /* Front USB 2.0 port */ + usb@50000 { + status = "okay"; + }; + + mdio { + phy0: ethernet-phy@0 { /* Marvell 88E1512 */ + reg = <0>; + }; + + phy1: ethernet-phy@1 { /* Marvell 88E1512 */ + reg = <1>; + }; + }; + + ethernet@70000 { + status = "okay"; + pinctrl-0 = <&ge0_rgmii_pins>; + pinctrl-names = "default"; + phy = <&phy1>; + phy-mode = "rgmii-id"; + }; + + ethernet@74000 { + pinctrl-0 = <&ge1_rgmii_pins>; + pinctrl-names = "default"; + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + }; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-0 = <&sata1_pwr_pin &sata2_pwr_pin + &sata3_pwr_pin &sata4_pwr_pin>; + pinctrl-names = "default"; + + sata1_regulator: sata1-regulator { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "SATA1 Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + startup-delay-us = <2000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>; + }; + + sata2_regulator: sata2-regulator { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "SATA2 Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + startup-delay-us = <4000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>; + }; + + sata3_regulator: sata3-regulator { + compatible = "regulator-fixed"; + reg = <3>; + regulator-name = "SATA3 Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + startup-delay-us = <6000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>; + }; + + sata4_regulator: sata4-regulator { + compatible = "regulator-fixed"; + reg = <4>; + regulator-name = "SATA4 Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + startup-delay-us = <8000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&pinctrl { + sata1_pwr_pin: sata1-pwr-pin { + marvell,pins = "mpp42"; + marvell,function = "gpio"; + }; + + sata2_pwr_pin: sata2-pwr-pin { + marvell,pins = "mpp44"; + marvell,function = "gpio"; + }; + + sata3_pwr_pin: sata3-pwr-pin { + marvell,pins = "mpp45"; + marvell,function = "gpio"; + }; + + sata4_pwr_pin: sata4-pwr-pin { + marvell,pins = "mpp46"; + marvell,function = "gpio"; + }; + + sata1_pres_pin: sata1-pres-pin { + marvell,pins = "mpp34"; + marvell,function = "gpio"; + }; + + sata2_pres_pin: sata2-pres-pin { + marvell,pins = "mpp35"; + marvell,function = "gpio"; + }; + + sata3_pres_pin: sata3-pres-pin { + marvell,pins = "mpp40"; + marvell,function = "gpio"; + }; + + sata4_pres_pin: sata4-pres-pin { + marvell,pins = "mpp41"; + marvell,function = "gpio"; + }; + + syno_id_bit0_pin: syno-id-bit0-pin { + marvell,pins = "mpp26"; + marvell,function = "gpio"; + }; + + syno_id_bit1_pin: syno-id-bit1-pin { + marvell,pins = "mpp28"; + marvell,function = "gpio"; + }; + + syno_id_bit2_pin: syno-id-bit2-pin { + marvell,pins = "mpp29"; + marvell,function = "gpio"; + }; + + fan1_alarm_pin: fan1-alarm-pin { + marvell,pins = "mpp33"; + marvell,function = "gpio"; + }; + + fan2_alarm_pin: fan2-alarm-pin { + marvell,pins = "mpp32"; + marvell,function = "gpio"; + }; +}; diff --git a/arch/arm/dts/armada-xp.dtsi b/arch/arm/dts/armada-xp.dtsi index 3de9b76..3fac39e 100644 --- a/arch/arm/dts/armada-xp.dtsi +++ b/arch/arm/dts/armada-xp.dtsi @@ -63,6 +63,7 @@ soc { compatible = "marvell,armadaxp-mbus", "simple-bus"; + u-boot,dm-pre-reloc; bootrom { compatible = "marvell,bootrom"; diff --git a/arch/arm/mach-kirkwood/include/mach/config.h b/arch/arm/mach-kirkwood/include/mach/config.h index d049395..0c4309f 100644 --- a/arch/arm/mach-kirkwood/include/mach/config.h +++ b/arch/arm/mach-kirkwood/include/mach/config.h @@ -135,4 +135,9 @@ #define CONFIG_SYS_I2C_SPEED 100000 #endif +/* Use common timer */ +#define CONFIG_SYS_TIMER_COUNTS_DOWN +#define CONFIG_SYS_TIMER_COUNTER (MVEBU_TIMER_BASE + 0x14) +#define CONFIG_SYS_TIMER_RATE CONFIG_SYS_TCLK + #endif /* _KW_CONFIG_H */ diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 79ff0e8..b962846 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -1,31 +1,74 @@ if ARCH_MVEBU +config ARMADA_38X + bool + +config ARMADA_XP + bool + +config MV78230 + bool + select ARMADA_XP + +config MV78260 + bool + select ARMADA_XP + +config MV78460 + bool + select ARMADA_XP + +config DB_88F6820_GP + bool + select ARMADA_38X + choice prompt "Marvell MVEBU (Armada XP/38x) board select" optional +config TARGET_CLEARFOG + bool "Support ClearFog" + select DB_88F6820_GP + config TARGET_DB_88F6820_GP bool "Support DB-88F6820-GP" + select DB_88F6820_GP config TARGET_DB_MV784MP_GP bool "Support db-mv784mp-gp" + select MV78460 + +config TARGET_DS414 + bool "Support Synology DS414" + select MV78230 config TARGET_MAXBCM bool "Support maxbcm" + select MV78460 endchoice -config SYS_SOC - default "mvebu" +config SYS_BOARD + default "clearfog" if TARGET_CLEARFOG + default "db-88f6820-gp" if TARGET_DB_88F6820_GP + default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP + default "ds414" if TARGET_DS414 + default "maxbcm" if TARGET_MAXBCM -config MVEBU_BOOTROM_UARTBOOT - bool "Use kwboot to boot via BootROM xmodem protocol" - help - This option provides support for booting via the Marvell - xmodem protocol, used by the kwboot tool. +config SYS_CONFIG_NAME + default "clearfog" if TARGET_CLEARFOG + default "db-88f6820-gp" if TARGET_DB_88F6820_GP + default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP + default "ds414" if TARGET_DS414 + default "maxbcm" if TARGET_MAXBCM - Please don't forget to configure the boot device in - the board specific kwbimage.cfg file this way: - BOOT_FROM uart +config SYS_VENDOR + default "Marvell" if TARGET_DB_MV784MP_GP + default "Marvell" if TARGET_DB_88F6820_GP + default "solidrun" if TARGET_CLEARFOG + default "Synology" if TARGET_DS414 + +config SYS_SOC + default "mvebu" endif diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index 21c56a4..b96b81b 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -15,8 +15,8 @@ else obj-y = cpu.o obj-y += dram.o ifndef CONFIG_SPL_BUILD -obj-$(CONFIG_SYS_MVEBU_DDR_A38X) += ../../../drivers/ddr/marvell/a38x/xor.o -obj-$(CONFIG_SYS_MVEBU_DDR_AXP) += ../../../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 obj-y += gpio.o obj-y += mbus.o @@ -24,7 +24,7 @@ obj-y += timer.o obj-$(CONFIG_SPL_BUILD) += spl.o obj-$(CONFIG_SPL_BUILD) += lowlevel_spl.o -obj-$(CONFIG_SYS_MVEBU_DDR_A38X) += serdes/a38x/ -obj-$(CONFIG_SYS_MVEBU_DDR_AXP) += serdes/axp/ +obj-$(CONFIG_ARMADA_38X) += serdes/a38x/ +obj-$(CONFIG_ARMADA_XP) += serdes/axp/ endif diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c index 895ad92..30b175c 100644 --- a/arch/arm/mach-mvebu/cpu.c +++ b/arch/arm/mach-mvebu/cpu.c @@ -1,11 +1,10 @@ /* - * Copyright (C) 2014-2015 Stefan Roese <sr@denx.de> + * Copyright (C) 2014-2016 Stefan Roese <sr@denx.de> * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> -#include <netdev.h> #include <ahci.h> #include <linux/mbus.h> #include <asm/io.h> @@ -50,25 +49,106 @@ int mvebu_soc_family(void) { u16 devid = (readl(MVEBU_REG_PCIE_DEVID) >> 16) & 0xffff; - if (devid == SOC_MV78460_ID) + switch (devid) { + case SOC_MV78230_ID: + case SOC_MV78260_ID: + case SOC_MV78460_ID: return MVEBU_SOC_AXP; - - if (devid == SOC_88F6810_ID || devid == SOC_88F6820_ID || - devid == SOC_88F6828_ID) + case SOC_88F6810_ID: + case SOC_88F6820_ID: + case SOC_88F6828_ID: return MVEBU_SOC_A38X; - + } return MVEBU_SOC_UNKNOWN; } #if defined(CONFIG_DISPLAY_CPUINFO) + +#if defined(CONFIG_ARMADA_38X) +/* SAR frequency values for Armada 38x */ +static const struct sar_freq_modes sar_freq_tab[] = { + { 0x0, 0x0, 666, 333, 333 }, + { 0x2, 0x0, 800, 400, 400 }, + { 0x4, 0x0, 1066, 533, 533 }, + { 0x6, 0x0, 1200, 600, 600 }, + { 0x8, 0x0, 1332, 666, 666 }, + { 0xc, 0x0, 1600, 800, 800 }, + { 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */ +}; +#else +/* SAR frequency values for Armada XP */ +static const struct sar_freq_modes sar_freq_tab[] = { + { 0xa, 0x5, 800, 400, 400 }, + { 0x1, 0x5, 1066, 533, 533 }, + { 0x2, 0x5, 1200, 600, 600 }, + { 0x2, 0x9, 1200, 600, 400 }, + { 0x3, 0x5, 1333, 667, 667 }, + { 0x4, 0x5, 1500, 750, 750 }, + { 0x4, 0x9, 1500, 750, 500 }, + { 0xb, 0x9, 1600, 800, 533 }, + { 0xb, 0xa, 1600, 800, 640 }, + { 0xb, 0x5, 1600, 800, 800 }, + { 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */ +}; +#endif + +void get_sar_freq(struct sar_freq_modes *sar_freq) +{ + u32 val; + u32 freq; + int i; + + val = readl(CONFIG_SAR_REG); /* SAR - Sample At Reset */ + freq = (val & SAR_CPU_FREQ_MASK) >> SAR_CPU_FREQ_OFFS; +#if !defined(CONFIG_ARMADA_38X) + /* + * Shift CPU0 clock frequency select bit from SAR2 register + * into correct position + */ + freq |= ((readl(CONFIG_SAR2_REG) & SAR2_CPU_FREQ_MASK) + >> SAR2_CPU_FREQ_OFFS) << 3; +#endif + for (i = 0; sar_freq_tab[i].val != 0xff; i++) { + if (sar_freq_tab[i].val == freq) { +#if defined(CONFIG_ARMADA_38X) + *sar_freq = sar_freq_tab[i]; + return; +#else + int k; + u8 ffc; + + ffc = (val & SAR_FFC_FREQ_MASK) >> + SAR_FFC_FREQ_OFFS; + for (k = i; sar_freq_tab[k].ffc != 0xff; k++) { + if (sar_freq_tab[k].ffc == ffc) { + *sar_freq = sar_freq_tab[k]; + return; + } + } + i = k; +#endif + } + } + + /* SAR value not found, return 0 for frequencies */ + *sar_freq = sar_freq_tab[i - 1]; +} + int print_cpuinfo(void) { u16 devid = (readl(MVEBU_REG_PCIE_DEVID) >> 16) & 0xffff; u8 revid = readl(MVEBU_REG_PCIE_REVID) & 0xff; + struct sar_freq_modes sar_freq; puts("SoC: "); switch (devid) { + case SOC_MV78230_ID: + puts("MV78230-"); + break; + case SOC_MV78260_ID: + puts("MV78260-"); + break; case SOC_MV78460_ID: puts("MV78460-"); break; @@ -89,13 +169,13 @@ int print_cpuinfo(void) if (mvebu_soc_family() == MVEBU_SOC_AXP) { switch (revid) { case 1: - puts("A0\n"); + puts("A0"); break; case 2: - puts("B0\n"); + puts("B0"); break; default: - printf("?? (%x)\n", revid); + printf("?? (%x)", revid); break; } } @@ -103,17 +183,20 @@ int print_cpuinfo(void) if (mvebu_soc_family() == MVEBU_SOC_A38X) { switch (revid) { case MV_88F68XX_Z1_ID: - puts("Z1\n"); + puts("Z1"); break; case MV_88F68XX_A0_ID: - puts("A0\n"); + puts("A0"); break; default: - printf("?? (%x)\n", revid); + printf("?? (%x)", revid); break; } } + get_sar_freq(&sar_freq); + printf(" at %d MHz\n", sar_freq.p_clk); + return 0; } #endif /* CONFIG_DISPLAY_CPUINFO */ @@ -199,10 +282,10 @@ static void setup_usb_phys(void) clrsetbits_le32(MV_USB_PHY_PLL_REG(1), 0x3ff, 0x605); /* Power up PLL and PHY channel */ - clrsetbits_le32(MV_USB_PHY_PLL_REG(2), 0, BIT(9)); + setbits_le32(MV_USB_PHY_PLL_REG(2), BIT(9)); /* Assert VCOCAL_START */ - clrsetbits_le32(MV_USB_PHY_PLL_REG(1), 0, BIT(21)); + setbits_le32(MV_USB_PHY_PLL_REG(1), BIT(21)); mdelay(1); @@ -211,18 +294,20 @@ static void setup_usb_phys(void) */ for (dev = 0; dev < 3; dev++) { - clrsetbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 3), 0, BIT(15)); + setbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 3), BIT(15)); /* Assert REG_RCAL_START in channel REG 1 */ - clrsetbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), 0, BIT(12)); + setbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), BIT(12)); udelay(40); - clrsetbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), BIT(12), 0); + clrbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), BIT(12)); } } +/* + * This function is not called from the SPL U-Boot version + */ int arch_cpu_init(void) { -#if !defined(CONFIG_SPL_BUILD) struct pl310_regs *const pl310 = (struct pl310_regs *)CONFIG_SYS_PL310_BASE; @@ -233,27 +318,26 @@ int arch_cpu_init(void) * still locked to cache. */ mmu_disable(); -#endif /* Linux expects the internal registers to be at 0xf1000000 */ writel(SOC_REGS_PHY_BASE, INTREG_BASE_ADDR_REG); set_cbar(SOC_REGS_PHY_BASE + 0xC000); -#if !defined(CONFIG_SPL_BUILD) /* * From this stage on, the SoC detection is working. As we have * configured the internal register base to the value used * in the macros / defines in the U-Boot header (soc.h). */ - /* - * To fully release / unlock this area from cache, we need - * to flush all caches and disable the L2 cache. - */ - icache_disable(); - dcache_disable(); - clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); -#endif + if (mvebu_soc_family() == MVEBU_SOC_A38X) { + /* + * To fully release / unlock this area from cache, we need + * to flush all caches and disable the L2 cache. + */ + icache_disable(); + dcache_disable(); + clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); + } /* * We need to call mvebu_mbus_probe() before calling @@ -326,30 +410,6 @@ int arch_misc_init(void) } #endif /* CONFIG_ARCH_MISC_INIT */ -#ifdef CONFIG_MVNETA -int cpu_eth_init(bd_t *bis) -{ - u32 enet_base[] = { MVEBU_EGIGA0_BASE, MVEBU_EGIGA1_BASE, - MVEBU_EGIGA2_BASE, MVEBU_EGIGA3_BASE }; - u8 phy_addr[] = CONFIG_PHY_ADDR; - int i; - - /* - * Only Armada XP supports all 4 ethernet interfaces. A38x has - * slightly different base addresses for its 2-3 interfaces. - */ - if (mvebu_soc_family() != MVEBU_SOC_AXP) { - enet_base[1] = MVEBU_EGIGA2_BASE; - enet_base[2] = MVEBU_EGIGA3_BASE; - } - - for (i = 0; i < ARRAY_SIZE(phy_addr); i++) - mvneta_initialize(bis, enet_base[i], i, phy_addr[i]); - - return 0; -} -#endif - #ifdef CONFIG_MV_SDHCI int board_mmc_init(bd_t *bis) { @@ -413,20 +473,43 @@ void scsi_init(void) } #endif -#ifndef CONFIG_SYS_DCACHE_OFF void enable_caches(void) { - struct pl310_regs *const pl310 = - (struct pl310_regs *)CONFIG_SYS_PL310_BASE; - - /* First disable L2 cache - may still be enable from BootROM */ - if (mvebu_soc_family() == MVEBU_SOC_A38X) - clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); - /* Avoid problem with e.g. neta ethernet driver */ invalidate_dcache_all(); /* Enable D-cache. I-cache is already enabled in start.S */ dcache_enable(); } -#endif + +void v7_outer_cache_enable(void) +{ + if (mvebu_soc_family() == MVEBU_SOC_AXP) { + struct pl310_regs *const pl310 = + (struct pl310_regs *)CONFIG_SYS_PL310_BASE; + u32 u; + + /* The L2 cache is already disabled at this point */ + + /* + * For Aurora cache in no outer mode, enable via the CP15 + * coprocessor broadcasting of cache commands to L2. + */ + asm volatile("mrc p15, 1, %0, c15, c2, 0" : "=r" (u)); + u |= BIT(8); /* Set the FW bit */ + asm volatile("mcr p15, 1, %0, c15, c2, 0" : : "r" (u)); + + isb(); + + /* Enable the L2 cache */ + setbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); + } +} + +void v7_outer_cache_disable(void) +{ + struct pl310_regs *const pl310 = + (struct pl310_regs *)CONFIG_SYS_PL310_BASE; + + clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); +} diff --git a/arch/arm/mach-mvebu/dram.c b/arch/arm/mach-mvebu/dram.c index ddc5b7e..a8ec5ea 100644 --- a/arch/arm/mach-mvebu/dram.c +++ b/arch/arm/mach-mvebu/dram.c @@ -12,11 +12,8 @@ #include <asm/arch/cpu.h> #include <asm/arch/soc.h> -#ifdef CONFIG_SYS_MVEBU_DDR_A38X -#include "../../../drivers/ddr/marvell/axp/xor.h" -#include "../../../drivers/ddr/marvell/axp/xor_regs.h" -#endif -#ifdef CONFIG_SYS_MVEBU_DDR_AXP +#if defined(CONFIG_ARCH_MVEBU) +/* Use common XOR definitions for A3x and AXP */ #include "../../../drivers/ddr/marvell/axp/xor.h" #include "../../../drivers/ddr/marvell/axp/xor_regs.h" #endif @@ -112,7 +109,7 @@ void mvebu_sdram_size_adjust(enum memory_bank bank) mvebu_sdram_bs_set(bank, size); } -#if defined(CONFIG_SYS_MVEBU_DDR_A38X) || defined(CONFIG_SYS_MVEBU_DDR_AXP) +#if defined(CONFIG_ARCH_MVEBU) static u32 xor_ctrl_save; static u32 xor_base_save; static u32 xor_mask_save; @@ -292,11 +289,18 @@ void dram_init_banksize(void) } } +#if defined(CONFIG_ARCH_MVEBU) void board_add_ram_info(int use_default) { + struct sar_freq_modes sar_freq; + + get_sar_freq(&sar_freq); + printf(" (%d MHz, ", sar_freq.d_clk); + if (ecc_enabled()) - printf(" (ECC"); + printf("ECC"); else - printf(" (ECC not"); + printf("ECC not"); printf(" enabled)"); } +#endif diff --git a/arch/arm/mach-mvebu/include/mach/config.h b/arch/arm/mach-mvebu/include/mach/config.h index 1d49cab..cc1fc5f 100644 --- a/arch/arm/mach-mvebu/include/mach/config.h +++ b/arch/arm/mach-mvebu/include/mach/config.h @@ -17,12 +17,22 @@ #include <asm/arch/soc.h> -#if defined(CONFIG_ARMADA_XP) +#if defined(CONFIG_ARMADA_XP) || defined(CONFIG_ARMADA_38X) +/* + * Set this for the common xor register definitions needed in dram.c + * for A38x as well here. + */ #define MV88F78X60 /* for the DDR training bin_hdr code */ #endif #define CONFIG_SYS_CACHELINE_SIZE 32 +#define CONFIG_SYS_L2_PL310 + +#ifdef CONFIG_SPL_BUILD +#define CONFIG_SKIP_LOWLEVEL_INIT /* disable board lowlevel_init */ +#endif + /* * By default kwbimage.cfg from board specific folder is used * If for some board, different configuration file need to be used, @@ -47,8 +57,7 @@ * SPI Flash configuration */ #ifdef CONFIG_CMD_SF -#define CONFIG_HARD_SPI 1 -#define CONFIG_KIRKWOOD_SPI 1 +#define CONFIG_KIRKWOOD_SPI #ifndef CONFIG_ENV_SPI_BUS # define CONFIG_ENV_SPI_BUS 0 #endif @@ -60,6 +69,9 @@ #endif #endif +/* Needed for SPI NOR booting in SPL */ +#define CONFIG_DM_SEQ_ALIAS 1 + /* * Ethernet Driver configuration */ @@ -85,9 +97,9 @@ #define CONFIG_SYS_I2C_SPEED 100000 #endif -/* Common SPL configuration */ -#ifndef CONFIG_SPL_LDSCRIPT -#define CONFIG_SPL_LDSCRIPT "arch/arm/mach-mvebu/u-boot-spl.lds" -#endif +/* Use common timer */ +#define CONFIG_SYS_TIMER_COUNTS_DOWN +#define CONFIG_SYS_TIMER_COUNTER (MVEBU_TIMER_BASE + 0x14) +#define CONFIG_SYS_TIMER_RATE 25000000 #endif /* __MVEBU_CONFIG_H */ diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h index 5e8bf0c..47f45c1 100644 --- a/arch/arm/mach-mvebu/include/mach/cpu.h +++ b/arch/arm/mach-mvebu/include/mach/cpu.h @@ -106,6 +106,14 @@ struct kwgpio_registers { u32 irq_level; }; +struct sar_freq_modes { + u8 val; + u8 ffc; /* Fabric Frequency Configuration */ + u32 p_clk; + u32 nb_clk; + u32 d_clk; +}; + /* Needed for dynamic (board-specific) mbus configuration */ extern struct mvebu_mbus_state mbus_state; @@ -123,6 +131,8 @@ void return_to_bootrom(void); int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks); +void get_sar_freq(struct sar_freq_modes *sar_freq); + /* * Highspeed SERDES PHY config init, ported from bin_hdr * to mainline U-Boot diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h index 22abde0..cb216bc 100644 --- a/arch/arm/mach-mvebu/include/mach/soc.h +++ b/arch/arm/mach-mvebu/include/mach/soc.h @@ -11,6 +11,8 @@ #ifndef _MVEBU_SOC_H #define _MVEBU_SOC_H +#define SOC_MV78230_ID 0x7823 +#define SOC_MV78260_ID 0x7826 #define SOC_MV78460_ID 0x7846 #define SOC_88F6810_ID 0x6810 #define SOC_88F6820_ID 0x6820 @@ -33,10 +35,11 @@ #define INTREG_BASE_ADDR_REG (INTREG_BASE + 0x20080) #if defined(CONFIG_SPL_BUILD) /* - * On A38x switching the regs base address without running from - * SDRAM doesn't seem to work. So let the SPL still use the - * default base address and switch to the new address in the - * main u-boot later. + * The SPL U-Boot version still runs with the default + * address for the internal registers, configured by + * the BootROM. Only the main U-Boot version uses the + * new internal register base address, that also is + * required for the Linux kernel. */ #define SOC_REGS_PHY_BASE 0xd0000000 #else @@ -47,10 +50,7 @@ #define MVEBU_SDRAM_SCRATCH (MVEBU_REGISTER(0x01504)) #define MVEBU_L2_CACHE_BASE (MVEBU_REGISTER(0x08000)) #define CONFIG_SYS_PL310_BASE MVEBU_L2_CACHE_BASE -#define MVEBU_SPI_BASE (MVEBU_REGISTER(0x10600)) #define MVEBU_TWSI_BASE (MVEBU_REGISTER(0x11000)) -#define MVEBU_UART0_BASE (MVEBU_REGISTER(0x12000)) -#define MVEBU_UART1_BASE (MVEBU_REGISTER(0x12100)) #define MVEBU_MPP_BASE (MVEBU_REGISTER(0x18000)) #define MVEBU_GPIO0_BASE (MVEBU_REGISTER(0x18100)) #define MVEBU_GPIO1_BASE (MVEBU_REGISTER(0x18140)) @@ -60,13 +60,9 @@ #define MVEBU_CPU_WIN_BASE (MVEBU_REGISTER(0x20000)) #define MVEBU_SDRAM_BASE (MVEBU_REGISTER(0x20180)) #define MVEBU_TIMER_BASE (MVEBU_REGISTER(0x20300)) -#define MVEBU_EGIGA2_BASE (MVEBU_REGISTER(0x30000)) -#define MVEBU_EGIGA3_BASE (MVEBU_REGISTER(0x34000)) #define MVEBU_REG_PCIE_BASE (MVEBU_REGISTER(0x40000)) #define MVEBU_AXP_USB_BASE (MVEBU_REGISTER(0x50000)) #define MVEBU_USB20_BASE (MVEBU_REGISTER(0x58000)) -#define MVEBU_EGIGA0_BASE (MVEBU_REGISTER(0x70000)) -#define MVEBU_EGIGA1_BASE (MVEBU_REGISTER(0x74000)) #define MVEBU_AXP_SATA_BASE (MVEBU_REGISTER(0xa0000)) #define MVEBU_SATA0_BASE (MVEBU_REGISTER(0xa8000)) #define MVEBU_NAND_BASE (MVEBU_REGISTER(0xd0000)) @@ -101,4 +97,49 @@ #define MVCPU_WIN_ENABLE CPU_WIN_ENABLE #define MVCPU_WIN_DISABLE CPU_WIN_DISABLE +#define COMPHY_REFCLK_ALIGNMENT (MVEBU_REGISTER(0x182f8)) + +/* BootROM error register (also includes some status infos) */ +#define CONFIG_BOOTROM_ERR_REG (MVEBU_REGISTER(0x182d0)) +#define BOOTROM_ERR_MODE_OFFS 28 +#define BOOTROM_ERR_MODE_MASK (0xf << BOOTROM_ERR_MODE_OFFS) +#define BOOTROM_ERR_MODE_UART 0x6 + +#if defined(CONFIG_ARMADA_38X) +/* SAR values for Armada 38x */ +#define CONFIG_SAR_REG (MVEBU_REGISTER(0x18600)) + +#define SAR_CPU_FREQ_OFFS 10 +#define SAR_CPU_FREQ_MASK (0x1f << SAR_CPU_FREQ_OFFS) +#define SAR_BOOT_DEVICE_OFFS 4 +#define SAR_BOOT_DEVICE_MASK (0x1f << SAR_BOOT_DEVICE_OFFS) + +#define BOOT_DEV_SEL_OFFS 4 +#define BOOT_DEV_SEL_MASK (0x3f << BOOT_DEV_SEL_OFFS) + +#define BOOT_FROM_UART 0x28 +#define BOOT_FROM_SPI 0x32 +#define BOOT_FROM_MMC 0x30 +#define BOOT_FROM_MMC_ALT 0x31 +#else +/* SAR values for Armada XP */ +#define CONFIG_SAR_REG (MVEBU_REGISTER(0x18230)) +#define CONFIG_SAR2_REG (MVEBU_REGISTER(0x18234)) + +#define SAR_CPU_FREQ_OFFS 21 +#define SAR_CPU_FREQ_MASK (0x7 << SAR_CPU_FREQ_OFFS) +#define SAR_FFC_FREQ_OFFS 24 +#define SAR_FFC_FREQ_MASK (0xf << SAR_FFC_FREQ_OFFS) +#define SAR2_CPU_FREQ_OFFS 20 +#define SAR2_CPU_FREQ_MASK (0x1 << SAR2_CPU_FREQ_OFFS) +#define SAR_BOOT_DEVICE_OFFS 5 +#define SAR_BOOT_DEVICE_MASK (0xf << SAR_BOOT_DEVICE_OFFS) + +#define BOOT_DEV_SEL_OFFS 5 +#define BOOT_DEV_SEL_MASK (0xf << BOOT_DEV_SEL_OFFS) + +#define BOOT_FROM_UART 0x2 +#define BOOT_FROM_SPI 0x3 +#endif + #endif /* _MVEBU_SOC_H */ diff --git a/arch/arm/mach-mvebu/lowlevel_spl.S b/arch/arm/mach-mvebu/lowlevel_spl.S index 2e2181e..49e0b90 100644 --- a/arch/arm/mach-mvebu/lowlevel_spl.S +++ b/arch/arm/mach-mvebu/lowlevel_spl.S @@ -5,7 +5,6 @@ #include <config.h> #include <linux/linkage.h> -#ifdef CONFIG_MVEBU_BOOTROM_UARTBOOT ENTRY(save_boot_params) stmfd sp!, {r0 - r12, lr} /* @ save registers on stack */ ldr r12, =CONFIG_SPL_BOOTROM_SAVE @@ -19,11 +18,6 @@ ENTRY(return_to_bootrom) mov r0, #0x0 /* @ return value: 0x0 NO_ERR */ ldmfd sp!, {r0 - r12, pc} /* @ restore regs and return */ ENDPROC(return_to_bootrom) -#else -ENTRY(save_boot_params) - b save_boot_params_ret -ENDPROC(save_boot_params) -#endif /* * cache_inv - invalidate Cache line diff --git a/arch/arm/mach-mvebu/mbus.c b/arch/arm/mach-mvebu/mbus.c index 346278e..df263bc 100644 --- a/arch/arm/mach-mvebu/mbus.c +++ b/arch/arm/mach-mvebu/mbus.c @@ -491,7 +491,7 @@ int mvebu_mbus_probe(struct mbus_win windows[], int count) #if defined(CONFIG_KIRKWOOD) mbus_state.soc = &kirkwood_mbus_data; #endif -#if defined(CONFIG_ARMADA_XP) +#if defined(CONFIG_ARCH_MVEBU) mbus_state.soc = &armada_370_xp_mbus_data; #endif diff --git a/arch/arm/mach-mvebu/serdes/axp/board_env_spec.h b/arch/arm/mach-mvebu/serdes/axp/board_env_spec.h index 36e0ed8..c8d9485 100644 --- a/arch/arm/mach-mvebu/serdes/axp/board_env_spec.h +++ b/arch/arm/mach-mvebu/serdes/axp/board_env_spec.h @@ -32,7 +32,7 @@ #define BOARD_ID_BASE 0x0 /* New board ID numbers */ -#define DB_88F78XX0_BP_ID (BOARD_ID_BASE) +#define DB_88F78XX0_BP_ID (BOARD_ID_BASE + 1) #define RD_78460_SERVER_ID (DB_88F78XX0_BP_ID + 1) #define DB_78X60_PCAC_ID (RD_78460_SERVER_ID + 1) #define FPGA_88F78XX0_ID (DB_78X60_PCAC_ID + 1) @@ -44,7 +44,7 @@ #define DB_784MP_GP_ID (RD_78460_SERVER_REV2_ID + 1) #define RD_78460_CUSTOMER_ID (DB_784MP_GP_ID + 1) #define MV_MAX_BOARD_ID (RD_78460_CUSTOMER_ID + 1) -#define INVALID_BAORD_ID 0xFFFFFFFF +#define INVALID_BOARD_ID 0xFFFFFFFF /* Sample at Reset */ #define MPP_SAMPLE_AT_RESET(id) (0x18230 + (id * 4)) diff --git a/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c b/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c index 702273a..afc0cef 100644 --- a/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c +++ b/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c @@ -75,16 +75,24 @@ static u32 board_id_get(void) #endif } -static u8 board_sat_r_get(u8 dev_num, u8 reg) +__weak u8 board_sat_r_get(u8 dev_num, u8 reg) { u8 data; u8 *dev; u32 board_id = board_id_get(); int ret; - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - switch (board_id) { + case DB_78X60_AMC_ID: + case DB_78X60_PCAC_REV2_ID: + case RD_78460_CUSTOMER_ID: + case RD_78460_SERVER_ID: + case RD_78460_SERVER_REV2_ID: + case DB_78X60_PCAC_ID: + return (0x1 << 1) | 1; + case FPGA_88F78XX0_ID: + case RD_78460_NAS_ID: + return (0x0 << 1) | 1; case DB_784MP_GP_ID: dev = rd78460gp_twsi_dev; @@ -94,15 +102,12 @@ static u8 board_sat_r_get(u8 dev_num, u8 reg) dev = db88f78xx0rev2_twsi_dev; break; - case DB_78X60_PCAC_ID: - case FPGA_88F78XX0_ID: - case DB_78X60_PCAC_REV2_ID: - case RD_78460_SERVER_REV2_ID: default: return 0; } /* Read MPP module ID */ + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); ret = i2c_read(dev[dev_num], 0, 1, (u8 *)&data, 1); if (ret) return MV_ERROR; @@ -190,8 +195,17 @@ __weak MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode) u16 ctrl_model_get(void) { - /* Right now only MV78460 supported */ + /* + * SoC version can't be autodetected. So we need to rely on a define + * from the config system here. + */ +#if defined(CONFIG_MV78230) + return MV_78230_DEV_ID; +#elif defined(CONFIG_MV78260) + return MV_78260_DEV_ID; +#else return MV_78460_DEV_ID; +#endif } u32 get_line_cfg(u32 line_num, MV_BIN_SERDES_CFG *info) @@ -202,6 +216,20 @@ u32 get_line_cfg(u32 line_num, MV_BIN_SERDES_CFG *info) return (info->line8_15 >> ((line_num - 8) << 2)) & 0xF; } +static int serdes_max_lines_get(void) +{ + switch (ctrl_model_get()) { + case MV_78230_DEV_ID: + return 7; + case MV_78260_DEV_ID: + return 12; + case MV_78460_DEV_ID: + return 16; + } + + return 0; +} + int serdes_phy_config(void) { int status = MV_OK; @@ -221,39 +249,19 @@ int serdes_phy_config(void) u8 device_rev; u32 rx_high_imp_mode; u16 ctrl_mode; - u32 board_id = board_id_get(); u32 pex_if; u32 pex_if_num; /* - * TODO: - * Right now we only support the MV78460 with 16 serdes lines + * Get max. serdes lines count */ - max_serdes_lines = 16; + max_serdes_lines = serdes_max_lines_get(); if (max_serdes_lines == 0) return MV_OK; - switch (board_id) { - case DB_78X60_AMC_ID: - case DB_78X60_PCAC_REV2_ID: - case RD_78460_CUSTOMER_ID: - case RD_78460_SERVER_ID: - case RD_78460_SERVER_REV2_ID: - case DB_78X60_PCAC_ID: - satr11 = (0x1 << 1) | 1; - break; - case FPGA_88F78XX0_ID: - case RD_78460_NAS_ID: - satr11 = (0x0 << 1) | 1; - break; - case DB_88F78XX0_BP_REV2_ID: - case DB_784MP_GP_ID: - case DB_88F78XX0_BP_ID: - satr11 = board_sat_r_get(1, 1); - if ((u8) MV_ERROR == (u8) satr11) - return MV_ERROR; - break; - } + satr11 = board_sat_r_get(1, 1); + if ((u8) MV_ERROR == (u8) satr11) + return MV_ERROR; board_modules_scan(); memset(addr, 0, sizeof(addr)); @@ -1356,19 +1364,19 @@ int serdes_phy_config(void) pex_if, PEX_DEVICE_AND_VENDOR_ID)); devId &= 0xFFFF; devId |= ((ctrl_mode << 16) & 0xffff0000); - DEBUG_INIT_S("Update Device ID PEX"); - DEBUG_INIT_D(pex_if, 1); - DEBUG_INIT_D(devId, 8); - DEBUG_INIT_S("\n"); + DEBUG_INIT_FULL_S("Update Device ID PEX"); + DEBUG_INIT_FULL_D(pex_if, 1); + DEBUG_INIT_FULL_D(devId, 8); + DEBUG_INIT_FULL_S("\n"); reg_write(PEX_CFG_DIRECT_ACCESS (pex_if, PEX_DEVICE_AND_VENDOR_ID), devId); if ((pex_if < 8) && (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4)) pex_if += 3; } - DEBUG_INIT_S("Update PEX Device ID 0x"); - DEBUG_INIT_D(ctrl_mode, 4); - DEBUG_INIT_S("0\n"); + DEBUG_INIT_FULL_S("Update PEX Device ID 0x"); + DEBUG_INIT_FULL_D(ctrl_mode, 4); + DEBUG_INIT_FULL_S("0\n"); } tmp = reg_read(PEX_DBG_STATUS_REG(0)); DEBUG_RD_REG(PEX_DBG_STATUS_REG(0), tmp); diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c index 0ab729a..0879873 100644 --- a/arch/arm/mach-mvebu/spl.c +++ b/arch/arm/mach-mvebu/spl.c @@ -1,10 +1,13 @@ /* - * Copyright (C) 2014 Stefan Roese <sr@denx.de> + * Copyright (C) 2014-2016 Stefan Roese <sr@denx.de> * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> +#include <dm.h> +#include <debug_uart.h> +#include <fdtdec.h> #include <spl.h> #include <asm/io.h> #include <asm/arch/cpu.h> @@ -12,14 +15,45 @@ DECLARE_GLOBAL_DATA_PTR; -u32 spl_boot_device(void) +static u32 get_boot_device(void) { -#if defined(CONFIG_SPL_SPI_FLASH_SUPPORT) - return BOOT_DEVICE_SPI; -#endif -#if defined(CONFIG_SPL_MMC_SUPPORT) - return BOOT_DEVICE_MMC1; + u32 val; + u32 boot_device; + + /* + * First check, if UART boot-mode is active. This can only + * be done, via the bootrom error register. Here the + * MSB marks if the UART mode is active. + */ + val = readl(CONFIG_BOOTROM_ERR_REG); + boot_device = (val & BOOTROM_ERR_MODE_MASK) >> BOOTROM_ERR_MODE_OFFS; + debug("BOOTROM_REG=0x%08x boot_device=0x%x\n", val, boot_device); + if (boot_device == BOOTROM_ERR_MODE_UART) + return BOOT_DEVICE_UART; + + /* + * Now check the SAR register for the strapped boot-device + */ + val = readl(CONFIG_SAR_REG); /* SAR - Sample At Reset */ + boot_device = (val & BOOT_DEV_SEL_MASK) >> BOOT_DEV_SEL_OFFS; + debug("SAR_REG=0x%08x boot_device=0x%x\n", val, boot_device); + switch (boot_device) { +#ifdef CONFIG_SPL_MMC_SUPPORT + case BOOT_FROM_MMC: + case BOOT_FROM_MMC_ALT: + return BOOT_DEVICE_MMC1; #endif + case BOOT_FROM_UART: + return BOOT_DEVICE_UART; + case BOOT_FROM_SPI: + default: + return BOOT_DEVICE_SPI; + }; +} + +u32 spl_boot_device(void) +{ + return get_boot_device(); } #ifdef CONFIG_SPL_MMC_SUPPORT @@ -31,18 +65,7 @@ u32 spl_boot_mode(void) void board_init_f(ulong dummy) { -#ifndef CONFIG_MVEBU_BOOTROM_UARTBOOT - /* - * Only call arch_cpu_init() when not returning to the - * Marvell BootROM, which is done when booting via - * the xmodem protocol (kwboot tool). Otherwise the - * internal register will get remapped and the BootROM - * can't continue to run correctly. - */ - - /* Linux expects the internal registers to be at 0xf1000000 */ - arch_cpu_init(); -#endif + int ret; /* * Pin muxing needs to be done before UART output, since @@ -51,6 +74,27 @@ void board_init_f(ulong dummy) */ board_early_init_f(); + /* Example code showing how to enable the debug UART on MVEBU */ +#ifdef EARLY_UART + /* + * Debug UART can be used from here if required: + * + * debug_uart_init(); + * printch('a'); + * printhex8(0x1234); + * printascii("string"); + */ +#endif + + ret = spl_init(); + if (ret) { + debug("spl_init() failed: %d\n", ret); + hang(); + } + + /* Use special translation offset for SPL */ + dm_set_translation_offset(0xd0000000 - 0xf1000000); + preloader_console_init(); timer_init(); @@ -61,7 +105,6 @@ void board_init_f(ulong dummy) /* Setup DDR */ ddr3_init(); -#ifdef CONFIG_MVEBU_BOOTROM_UARTBOOT /* * Return to the BootROM to continue the Marvell xmodem * UART boot protocol. As initiated by the kwboot tool. @@ -73,6 +116,6 @@ void board_init_f(ulong dummy) * need to return to the BootROM to enable this xmodem * UART download. */ - return_to_bootrom(); -#endif + if (get_boot_device() == BOOT_DEVICE_UART) + return_to_bootrom(); } diff --git a/arch/arm/mach-mvebu/timer.c b/arch/arm/mach-mvebu/timer.c index 5449a89..f5c2eaa 100644 --- a/arch/arm/mach-mvebu/timer.c +++ b/arch/arm/mach-mvebu/timer.c @@ -2,6 +2,8 @@ * Copyright (C) Marvell International Ltd. and its affiliates * Written-by: Prafulla Wadaskar <prafulla@marvell.com> * + * Copyright (C) 2015 Stefan Roese <sr@denx.de> + * * SPDX-License-Identifier: GPL-2.0+ */ @@ -9,108 +11,14 @@ #include <asm/io.h> #include <asm/arch/soc.h> -#define UBOOT_CNTR 0 /* counter to use for U-Boot timer */ - -/* - * ARM Timers Registers Map - */ -#define CNTMR_CTRL_REG &tmr_regs->ctrl -#define CNTMR_RELOAD_REG(tmrnum) &tmr_regs->tmr[tmrnum].reload -#define CNTMR_VAL_REG(tmrnum) &tmr_regs->tmr[tmrnum].val - -/* - * ARM Timers Control Register - * CPU_TIMERS_CTRL_REG (CTCR) - */ -#define CTCR_ARM_TIMER_EN_OFFS(cntr) (cntr * 2) -#define CTCR_ARM_TIMER_EN(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS(cntr)) - -#define CTCR_ARM_TIMER_AUTO_OFFS(cntr) ((cntr * 2) + 1) -#define CTCR_ARM_TIMER_AUTO_EN(cntr) (1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) - -/* Only Armada XP have the 25MHz enable bit (Kirkwood doesn't) */ -#if defined(CONFIG_ARMADA_XP) -#define CTCR_ARM_TIMER_25MHZ_OFFS(cntr) (cntr + 11) -#define CTCR_ARM_TIMER_25MHZ(cntr) (1 << CTCR_ARM_TIMER_25MHZ_OFFS(cntr)) -#else -#define CTCR_ARM_TIMER_25MHZ(cntr) 0 -#endif - -#define TIMER_LOAD_VAL 0xffffffff - -#define timestamp gd->arch.tbl -#define lastdec gd->arch.lastinc - -static int init_done __attribute__((section(".data"))) = 0; - -/* Timer reload and current value registers */ -struct kwtmr_val { - u32 reload; /* Timer reload reg */ - u32 val; /* Timer value reg */ -}; - -/* Timer registers */ -struct kwtmr_registers { - u32 ctrl; /* Timer control reg */ - u32 pad[3]; - struct kwtmr_val tmr[4]; - u32 wdt_reload; - u32 wdt_val; -}; - DECLARE_GLOBAL_DATA_PTR; -static struct kwtmr_registers *tmr_regs = - (struct kwtmr_registers *)MVEBU_TIMER_BASE; - -static inline ulong read_timer(void) -{ - return readl(CNTMR_VAL_REG(UBOOT_CNTR)) / (CONFIG_SYS_TCLK / 1000); -} - -ulong get_timer_masked(void) -{ - ulong now = read_timer(); - - if (lastdec >= now) { - /* normal mode */ - timestamp += lastdec - now; - } else { - /* we have an overflow ... */ - timestamp += lastdec + - (TIMER_LOAD_VAL / (CONFIG_SYS_TCLK / 1000)) - now; - } - lastdec = now; +#define TIMER_LOAD_VAL 0xffffffff - return timestamp; -} - -ulong get_timer(ulong base) -{ - return get_timer_masked() - base; -} - -void __udelay(unsigned long usec) -{ - uint current; - ulong delayticks; - - current = readl(CNTMR_VAL_REG(UBOOT_CNTR)); - delayticks = (usec * (CONFIG_SYS_TCLK / 1000000)); - - if (current < delayticks) { - delayticks -= current; - while (readl(CNTMR_VAL_REG(UBOOT_CNTR)) < current) ; - while ((TIMER_LOAD_VAL - delayticks) < - readl(CNTMR_VAL_REG(UBOOT_CNTR))) ; - } else { - while (readl(CNTMR_VAL_REG(UBOOT_CNTR)) > - (current - delayticks)) ; - } -} +static int init_done __attribute__((section(".data"))) = 0; /* - * init the counter + * Timer initialization */ int timer_init(void) { @@ -120,35 +28,15 @@ int timer_init(void) init_done = 1; /* load value into timer */ - writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR)); - writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR)); + writel(TIMER_LOAD_VAL, MVEBU_TIMER_BASE + 0x10); + writel(TIMER_LOAD_VAL, MVEBU_TIMER_BASE + 0x14); +#if defined(CONFIG_ARCH_MVEBU) + /* On Armada XP / 38x ..., the 25MHz clock source needs to be enabled */ + setbits_le32(MVEBU_TIMER_BASE + 0x00, BIT(11)); +#endif /* enable timer in auto reload mode */ - clrsetbits_le32(CNTMR_CTRL_REG, CTCR_ARM_TIMER_25MHZ(UBOOT_CNTR), - CTCR_ARM_TIMER_EN(UBOOT_CNTR) | - CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR)); - - /* init the timestamp and lastdec value */ - lastdec = read_timer(); - timestamp = 0; + setbits_le32(MVEBU_TIMER_BASE + 0x00, 0x3); return 0; } - -/* - * This function is derived from PowerPC code (read timebase as long long). - * On ARM it just returns the timer value. - */ -unsigned long long get_ticks(void) -{ - return get_timer(0); -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -ulong get_tbclk (void) -{ - return (ulong)CONFIG_SYS_HZ; -} diff --git a/arch/arm/mach-mvebu/u-boot-spl.lds b/arch/arm/mach-mvebu/u-boot-spl.lds deleted file mode 100644 index eee1db4..0000000 --- a/arch/arm/mach-mvebu/u-boot-spl.lds +++ /dev/null @@ -1,57 +0,0 @@ -/* - * (C) Copyright 2002 - * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> - * - * (C) Copyright 2010 - * Texas Instruments, <www.ti.com> - * Aneesh V <aneesh@ti.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ - LENGTH = CONFIG_SPL_MAX_SIZE } -MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ - LENGTH = CONFIG_SPL_BSS_MAX_SIZE } - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -ENTRY(_start) -SECTIONS -{ - .text : - { - __start = .; - arch/arm/cpu/armv7/start.o (.text*) - *(.text*) - *(.vectors) - } >.sram - - . = ALIGN(4); - .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram - - . = ALIGN(4); - .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram - - . = ALIGN(4); - .u_boot_list : { - KEEP(*(SORT(.u_boot_list*_i2c_*))); - } >.sram - - . = ALIGN(4); - __image_copy_end = .; - - .end : - { - *(.__end) - } - - .bss : - { - . = ALIGN(4); - __bss_start = .; - *(.bss*) - . = ALIGN(4); - __bss_end = .; - } >.sdram -} diff --git a/arch/arm/mvebu-common/Makefile b/arch/arm/mvebu-common/Makefile deleted file mode 100644 index de243fe..0000000 --- a/arch/arm/mvebu-common/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# (C) Copyright 2009 -# Marvell Semiconductor <www.marvell.com> -# Written-by: Prafulla Wadaskar <prafulla@marvell.com> -# -# SPDX-License-Identifier: GPL-2.0+ -# - -obj-y = dram.o -obj-y += gpio.o -obj-$(CONFIG_ARMADA_XP) += mbus.o -obj-y += timer.o - -obj-y += serdes/ diff --git a/board/Marvell/db-88f6820-gp/Kconfig b/board/Marvell/db-88f6820-gp/Kconfig deleted file mode 100644 index f12b968..0000000 --- a/board/Marvell/db-88f6820-gp/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -if TARGET_DB_88F6820_GP - -config SYS_BOARD - default "db-88f6820-gp" - -config SYS_VENDOR - default "Marvell" - -config SYS_CONFIG_NAME - default "db-88f6820-gp" - -endif diff --git a/board/Marvell/db-88f6820-gp/kwbimage.cfg b/board/Marvell/db-88f6820-gp/kwbimage.cfg index cc05792..1f748db 100644 --- a/board/Marvell/db-88f6820-gp/kwbimage.cfg +++ b/board/Marvell/db-88f6820-gp/kwbimage.cfg @@ -9,4 +9,4 @@ VERSION 1 BOOT_FROM spi # Binary Header (bin_hdr) with DDR3 training code -BINARY spl/u-boot-spl.bin 0000005b 00000068 +BINARY spl/u-boot-spl-dtb.bin 0000005b 00000068 diff --git a/board/Marvell/db-mv784mp-gp/Kconfig b/board/Marvell/db-mv784mp-gp/Kconfig deleted file mode 100644 index 428a5e1..0000000 --- a/board/Marvell/db-mv784mp-gp/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -if TARGET_DB_MV784MP_GP - -config SYS_BOARD - default "db-mv784mp-gp" - -config SYS_VENDOR - default "Marvell" - -config SYS_CONFIG_NAME - default "db-mv784mp-gp" - -endif diff --git a/board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c b/board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c index d7aa149..9305284 100644 --- a/board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c +++ b/board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c @@ -87,40 +87,32 @@ int board_eth_init(bd_t *bis) return pci_eth_init(bis); } -#ifdef CONFIG_RESET_PHY_R -/* Configure and enable MV88E1545 PHY */ -void reset_phy(void) +int board_phy_config(struct phy_device *phydev) { - u8 phy_addr[] = CONFIG_PHY_ADDR; - u16 devadr = phy_addr[0]; - char *name = "neta0"; u16 reg; - if (miiphy_set_current_dev(name)) - return; - /* Enable QSGMII AN */ /* Set page to 4 */ - miiphy_write(name, devadr, 0x16, 4); + phy_write(phydev, MDIO_DEVAD_NONE, 0x16, 4); /* Enable AN */ - miiphy_write(name, devadr, 0x0, 0x1140); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0, 0x1140); /* Set page to 0 */ - miiphy_write(name, devadr, 0x16, 0); + phy_write(phydev, MDIO_DEVAD_NONE, 0x16, 0); /* Phy C_ANEG */ - miiphy_read(name, devadr, 0x4, ®); + reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x4); reg |= 0x1E0; - miiphy_write(name, devadr, 0x4, reg); + phy_write(phydev, MDIO_DEVAD_NONE, 0x4, reg); /* Soft-Reset */ - miiphy_write(name, devadr, 22, 0x0000); - miiphy_write(name, devadr, 0, 0x9140); + phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000); + phy_write(phydev, MDIO_DEVAD_NONE, 0, 0x9140); /* Power up the phy */ - miiphy_read(name, devadr, ETH_PHY_CTRL_REG, ®); + reg = phy_read(phydev, MDIO_DEVAD_NONE, ETH_PHY_CTRL_REG); reg &= ~(ETH_PHY_CTRL_POWER_DOWN_MASK); - miiphy_write(name, devadr, ETH_PHY_CTRL_REG, reg); + phy_write(phydev, MDIO_DEVAD_NONE, ETH_PHY_CTRL_REG, reg); - printf("88E1545 Initialized on %s\n", name); + printf("88E1545 Initialized\n"); + return 0; } -#endif /* CONFIG_RESET_PHY_R */ diff --git a/board/Marvell/db-mv784mp-gp/kwbimage.cfg b/board/Marvell/db-mv784mp-gp/kwbimage.cfg index cc05792..1f748db 100644 --- a/board/Marvell/db-mv784mp-gp/kwbimage.cfg +++ b/board/Marvell/db-mv784mp-gp/kwbimage.cfg @@ -9,4 +9,4 @@ VERSION 1 BOOT_FROM spi # Binary Header (bin_hdr) with DDR3 training code -BINARY spl/u-boot-spl.bin 0000005b 00000068 +BINARY spl/u-boot-spl-dtb.bin 0000005b 00000068 diff --git a/board/Synology/common/Makefile b/board/Synology/common/Makefile new file mode 100644 index 0000000..e66aeb8 --- /dev/null +++ b/board/Synology/common/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2015 Phil Sutter <phil@nwl.cc> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := cmd_syno.o diff --git a/board/Synology/common/cmd_syno.c b/board/Synology/common/cmd_syno.c new file mode 100644 index 0000000..20544e2 --- /dev/null +++ b/board/Synology/common/cmd_syno.c @@ -0,0 +1,227 @@ +/* + * Commands to deal with Synology specifics. + * + * Copyright (C) 2015 Phil Sutter <phil@nwl.cc> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <spi.h> +#include <spi_flash.h> +#include <linux/mtd/mtd.h> + +#include <asm/io.h> +#include "../drivers/ddr/marvell/axp/ddr3_init.h" + +#define ETH_ALEN 6 +#define ETHADDR_MAX 4 +#define SYNO_SN_TAG "SN=" +#define SYNO_CHKSUM_TAG "CHK=" + + +static int do_syno_populate(int argc, char * const argv[]) +{ + unsigned int bus = CONFIG_SF_DEFAULT_BUS; + unsigned int cs = CONFIG_SF_DEFAULT_CS; + unsigned int speed = CONFIG_SF_DEFAULT_SPEED; + unsigned int mode = CONFIG_SF_DEFAULT_MODE; + struct spi_flash *flash; + unsigned long addr = 0x80000; /* XXX: parameterize this? */ + loff_t offset = 0x007d0000; + loff_t len = 0x00010000; + char *buf, *bufp; + char var[128]; + char val[128]; + int ret, n; + + /* XXX: arg parsing to select flash here? */ + + flash = spi_flash_probe(bus, cs, speed, mode); + if (!flash) { + printf("Failed to initialize SPI flash at %u:%u\n", bus, cs); + return 1; + } + + buf = map_physmem(addr, len, MAP_WRBACK); + if (!buf) { + puts("Failed to map physical memory\n"); + return 1; + } + + ret = spi_flash_read(flash, offset, len, buf); + if (ret) { + puts("Failed to read from SPI flash\n"); + goto out_unmap; + } + + for (n = 0; n < ETHADDR_MAX; n++) { + char ethaddr[ETH_ALEN]; + int i, sum = 0; + unsigned char csum = 0; + + for (i = 0, bufp = buf + n * 7; i < ETH_ALEN; i++) { + sum += bufp[i]; + csum += bufp[i]; + ethaddr[i] = bufp[i]; + } + if (!sum) /* MAC address empty */ + continue; + if (csum != bufp[i]) { /* seventh byte is checksum value */ + printf("Invalid MAC address for interface %d!\n", n); + continue; + } + if (n == 0) + sprintf(var, "ethaddr"); + else + sprintf(var, "eth%daddr", n); + snprintf(val, sizeof(val) - 1, + "%02x:%02x:%02x:%02x:%02x:%02x", + ethaddr[0], ethaddr[1], ethaddr[2], + ethaddr[3], ethaddr[4], ethaddr[5]); + printf("parsed %s = %s\n", var, val); + setenv(var, val); + } + if (!strncmp(buf + 32, SYNO_SN_TAG, strlen(SYNO_SN_TAG))) { + char *snp, *csump; + int csum = 0; + unsigned long c; + + snp = bufp = buf + 32 + strlen(SYNO_SN_TAG); + for (n = 0; bufp[n] && bufp[n] != ','; n++) + csum += bufp[n]; + bufp[n] = '\0'; + + /* should come right after, but you never know */ + bufp = strstr(bufp + n + 1, SYNO_CHKSUM_TAG); + if (!bufp) { + printf("Serial number checksum tag missing!\n"); + goto out_unmap; + } + + csump = bufp += strlen(SYNO_CHKSUM_TAG); + for (n = 0; bufp[n] && bufp[n] != ','; n++) + ; + bufp[n] = '\0'; + + if (strict_strtoul(csump, 10, &c) || c != csum) { + puts("Invalid serial number found!\n"); + ret = 1; + goto out_unmap; + } + printf("parsed SN = %s\n", snp); + setenv("SN", snp); + } else { /* old style format */ + unsigned char csum = 0; + + for (n = 0, bufp = buf + 32; n < 10; n++) + csum += bufp[n]; + + if (csum != bufp[n]) { + puts("Invalid serial number found!\n"); + ret = 1; + goto out_unmap; + } + bufp[n] = '\0'; + printf("parsed SN = %s\n", buf + 32); + setenv("SN", buf + 32); + } +out_unmap: + unmap_physmem(buf, len); + return ret; +} + +/* map bit position to function in POWER_MNG_CTRL_REG */ +static const char * const pwr_mng_bit_func[] = { + "audio", + "ge3", "ge2", "ge1", "ge0", + "pcie00", "pcie01", "pcie02", "pcie03", + "pcie10", "pcie11", "pcie12", "pcie13", + "bp", + "sata0_link", "sata0_core", + "lcd", + "sdio", + "usb0", "usb1", "usb2", + "idma", "xor0", "crypto", + NULL, + "tdm", + "pcie20", "pcie30", + "xor1", + "sata1_link", "sata1_core", + NULL, +}; + +static int do_syno_clk_gate(int argc, char * const argv[]) +{ + u32 pwr_mng_ctrl_reg = reg_read(POWER_MNG_CTRL_REG); + const char *func, *state; + int i, val; + + if (argc < 2) + return -1; + + if (!strcmp(argv[1], "get")) { + puts("Clock Gating:\n"); + for (i = 0; i < 32; i++) { + func = pwr_mng_bit_func[i]; + if (!func) + continue; + state = pwr_mng_ctrl_reg & (1 << i) ? "ON" : "OFF"; + printf("%s:\t\t%s\n", func, state); + } + return 0; + } + if (argc < 4) + return -1; + if (!strcmp(argv[1], "set")) { + func = argv[2]; + state = argv[3]; + for (i = 0; i < 32; i++) { + if (!pwr_mng_bit_func[i]) + continue; + if (!strcmp(func, pwr_mng_bit_func[i])) + break; + } + if (i == 32) { + printf("Error: name '%s' not known\n", func); + return -1; + } + val = state[0] != '0'; + pwr_mng_ctrl_reg |= (val << i); + pwr_mng_ctrl_reg &= ~(!val << i); + reg_write(POWER_MNG_CTRL_REG, pwr_mng_ctrl_reg); + } + return 0; +} + +static int do_syno(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + const char *cmd; + int ret = 0; + + if (argc < 2) + goto usage; + + cmd = argv[1]; + --argc; + ++argv; + + if (!strcmp(cmd, "populate_env")) + ret = do_syno_populate(argc, argv); + else if (!strcmp(cmd, "clk_gate")) + ret = do_syno_clk_gate(argc, argv); + + if (ret != -1) + return ret; +usage: + return CMD_RET_USAGE; +} + +U_BOOT_CMD( + syno, 5, 1, do_syno, + "Synology specific commands", + "populate_env - Read vendor data from SPI flash into environment\n" + "clk_gate (get|set name 1|0) - Manage clock gating\n" +); diff --git a/board/Synology/ds414/Makefile b/board/Synology/ds414/Makefile new file mode 100644 index 0000000..0f4c32d --- /dev/null +++ b/board/Synology/ds414/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2015 Phil Sutter <phil@nwl.cc> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := ds414.o diff --git a/board/Synology/ds414/ds414.c b/board/Synology/ds414/ds414.c new file mode 100644 index 0000000..d563e89 --- /dev/null +++ b/board/Synology/ds414/ds414.c @@ -0,0 +1,185 @@ +/* + * + * Copyright (C) 2015 Phil Sutter <phil@nwl.cc> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <miiphy.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/soc.h> +#include <linux/mbus.h> + +#include "../drivers/ddr/marvell/axp/ddr3_hw_training.h" +#include "../arch/arm/mach-mvebu/serdes/axp/high_speed_env_spec.h" +#include "../arch/arm/mach-mvebu/serdes/axp/board_env_spec.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* GPP and MPP settings as found in mvBoardEnvSpec.c of Synology's U-Boot */ + +#define DS414_GPP_OUT_VAL_LOW (BIT(25) | BIT(30)) +#define DS414_GPP_OUT_VAL_MID (BIT(10) | BIT(15)) +#define DS414_GPP_OUT_VAL_HIGH (0) + +#define DS414_GPP_OUT_POL_LOW (0) +#define DS414_GPP_OUT_POL_MID (0) +#define DS414_GPP_OUT_POL_HIGH (0) + +#define DS414_GPP_OUT_ENA_LOW (~(BIT(25) | BIT(30))) +#define DS414_GPP_OUT_ENA_MID (~(BIT(10) | BIT(12) | \ + BIT(13) | BIT(14) | BIT(15))) +#define DS414_GPP_OUT_ENA_HIGH (~0) + +static const u32 ds414_mpp_control[] = { + 0x11111111, + 0x22221111, + 0x22222222, + 0x00000000, + 0x11110000, + 0x00004000, + 0x00000000, + 0x00000000, + 0x00000000 +}; + +/* DDR3 static MC configuration */ + +/* 1G_v1 (4x2Gbits) adapted by DS414 */ +MV_DRAM_MC_INIT syno_ddr3_b0_667_1g_v1[MV_MAX_DDR3_STATIC_SIZE] = { + {0x00001400, 0x73014A28}, /*DDR SDRAM Configuration Register */ + {0x00001404, 0x30000800}, /*Dunit Control Low Register */ + {0x00001408, 0x44148887}, /*DDR SDRAM Timing (Low) Register */ + {0x0000140C, 0x3AD83FEA}, /*DDR SDRAM Timing (High) Register */ + + {0x00001410, 0x14000000}, /*DDR SDRAM Address Control Register */ + + {0x00001414, 0x00000000}, /*DDR SDRAM Open Pages Control Register */ + {0x00001418, 0x00000e00}, /*DDR SDRAM Operation Register */ + {0x00001420, 0x00000004}, /*DDR SDRAM Extended Mode Register */ + {0x00001424, 0x0000F3FF}, /*Dunit Control High Register */ + {0x00001428, 0x000F8830}, /*Dunit Control High Register */ + {0x0000142C, 0x054C36F4}, /*Dunit Control High Register */ + {0x0000147C, 0x0000C671}, + + {0x000014a0, 0x00000001}, + {0x000014a8, 0x00000100}, /*2:1 */ + {0x00020220, 0x00000006}, + + {0x00001494, 0x00010000}, /*DDR SDRAM ODT Control (Low) Register */ + {0x00001498, 0x00000000}, /*DDR SDRAM ODT Control (High) Register */ + {0x0000149C, 0x00000001}, /*DDR Dunit ODT Control Register */ + + {0x000014C0, 0x192424C9}, /* DRAM address and Control Driving Strenght */ + {0x000014C4, 0x0AAA24C9}, /* DRAM Data and DQS Driving Strenght */ + + {0x000200e8, 0x3FFF0E01}, /* DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the training sequence*/ + {0x00020184, 0x3FFFFFE0}, /* DO NOT Modify - Close fast path Window to - 2G */ + + {0x0001504, 0x3FFFFFE1}, /* CS0 Size */ + {0x000150C, 0x00000000}, /* CS1 Size */ + {0x0001514, 0x00000000}, /* CS2 Size */ + {0x000151C, 0x00000000}, /* CS3 Size */ + + {0x00001538, 0x00000009}, /*Read Data Sample Delays Register */ + {0x0000153C, 0x00000009}, /*Read Data Ready Delay Register */ + + {0x000015D0, 0x00000650}, /*MR0 */ + {0x000015D4, 0x00000044}, /*MR1 */ + {0x000015D8, 0x00000010}, /*MR2 */ + {0x000015DC, 0x00000000}, /*MR3 */ + + {0x000015E4, 0x00203c18}, /*ZQC Configuration Register */ + {0x000015EC, 0xF800A225}, /*DDR PHY */ + + {0x0, 0x0} +}; + +MV_DRAM_MODES ds414_ddr_modes[MV_DDR3_MODES_NUMBER] = { + {"ds414_1333-667", 0x3, 0x5, 0x0, A0, syno_ddr3_b0_667_1g_v1, NULL}, +}; + +extern MV_SERDES_CHANGE_M_PHY serdes_change_m_phy[]; + +MV_BIN_SERDES_CFG ds414_serdes_cfg[] = { + { MV_PEX_ROOT_COMPLEX, 0x02011111, 0x00000000, + { PEX_BUS_MODE_X4, PEX_BUS_MODE_X1, PEX_BUS_DISABLED, + PEX_BUS_DISABLED }, + 0x0040, serdes_change_m_phy + } +}; + +MV_DRAM_MODES *ddr3_get_static_ddr_mode(void) +{ + return &ds414_ddr_modes[0]; +} + +MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode) +{ + return &ds414_serdes_cfg[0]; +} + +u8 board_sat_r_get(u8 dev_num, u8 reg) +{ + return (0x1 << 1 | 1); +} + +int board_early_init_f(void) +{ + int i; + + /* Set GPP Out value */ + reg_write(GPP_DATA_OUT_REG(0), DS414_GPP_OUT_VAL_LOW); + reg_write(GPP_DATA_OUT_REG(1), DS414_GPP_OUT_VAL_MID); + reg_write(GPP_DATA_OUT_REG(2), DS414_GPP_OUT_VAL_HIGH); + + /* set GPP polarity */ + reg_write(GPP_DATA_IN_POL_REG(0), DS414_GPP_OUT_POL_LOW); + reg_write(GPP_DATA_IN_POL_REG(1), DS414_GPP_OUT_POL_MID); + reg_write(GPP_DATA_IN_POL_REG(2), DS414_GPP_OUT_POL_HIGH); + + /* Set GPP Out Enable */ + reg_write(GPP_DATA_OUT_EN_REG(0), DS414_GPP_OUT_ENA_LOW); + reg_write(GPP_DATA_OUT_EN_REG(1), DS414_GPP_OUT_ENA_MID); + reg_write(GPP_DATA_OUT_EN_REG(2), DS414_GPP_OUT_ENA_HIGH); + + for (i = 0; i < ARRAY_SIZE(ds414_mpp_control); i++) + reg_write(MPP_CONTROL_REG(i), ds414_mpp_control[i]); + + return 0; +} + +int board_init(void) +{ + u32 pwr_mng_ctrl_reg; + + /* Adress of boot parameters */ + gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100; + + /* Gate unused clocks + * + * Note: Disabling unused PCIe lanes will hang PCI bus scan. + * Once this is resolved, bits 10-12, 26 and 27 can be + * unset here as well. + */ + pwr_mng_ctrl_reg = reg_read(POWER_MNG_CTRL_REG); + pwr_mng_ctrl_reg &= ~(BIT(0)); /* Audio */ + pwr_mng_ctrl_reg &= ~(BIT(1) | BIT(2)); /* GE3, GE2 */ + pwr_mng_ctrl_reg &= ~(BIT(14) | BIT(15)); /* SATA0 link and core */ + pwr_mng_ctrl_reg &= ~(BIT(16)); /* LCD */ + pwr_mng_ctrl_reg &= ~(BIT(17)); /* SDIO */ + pwr_mng_ctrl_reg &= ~(BIT(19) | BIT(20)); /* USB1 and USB2 */ + pwr_mng_ctrl_reg &= ~(BIT(29) | BIT(30)); /* SATA1 link and core */ + reg_write(POWER_MNG_CTRL_REG, pwr_mng_ctrl_reg); + + return 0; +} + +int checkboard(void) +{ + puts("Board: DS414\n"); + + return 0; +} diff --git a/board/Synology/ds414/kwbimage.cfg b/board/Synology/ds414/kwbimage.cfg new file mode 100644 index 0000000..1f748db --- /dev/null +++ b/board/Synology/ds414/kwbimage.cfg @@ -0,0 +1,12 @@ +# +# Copyright (C) 2014 Stefan Roese <sr@denx.de> +# + +# Armada XP uses version 1 image format +VERSION 1 + +# Boot Media configurations +BOOT_FROM spi + +# Binary Header (bin_hdr) with DDR3 training code +BINARY spl/u-boot-spl-dtb.bin 0000005b 00000068 diff --git a/board/maxbcm/Kconfig b/board/maxbcm/Kconfig deleted file mode 100644 index 2edccfe..0000000 --- a/board/maxbcm/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -if TARGET_MAXBCM - -config SYS_BOARD - default "maxbcm" - -config SYS_CONFIG_NAME - default "maxbcm" - -endif diff --git a/board/maxbcm/kwbimage.cfg b/board/maxbcm/kwbimage.cfg index cc05792..1f748db 100644 --- a/board/maxbcm/kwbimage.cfg +++ b/board/maxbcm/kwbimage.cfg @@ -9,4 +9,4 @@ VERSION 1 BOOT_FROM spi # Binary Header (bin_hdr) with DDR3 training code -BINARY spl/u-boot-spl.bin 0000005b 00000068 +BINARY spl/u-boot-spl-dtb.bin 0000005b 00000068 diff --git a/board/maxbcm/maxbcm.c b/board/maxbcm/maxbcm.c index 119ba4c..db6ad99 100644 --- a/board/maxbcm/maxbcm.c +++ b/board/maxbcm/maxbcm.c @@ -138,17 +138,15 @@ int checkboard(void) return 0; } -#ifdef CONFIG_RESET_PHY_R /* Configure and enable MV88E6185 switch */ -void reset_phy(void) +int board_phy_config(struct phy_device *phydev) { - char *name = "neta0"; - - if (miiphy_set_current_dev(name)) - return; - - /* todo: fill this with the real setup / config code */ - - printf("88E6185 Initialized on %s\n", name); + /* + * todo: + * Fill this with the real setup / config code. + * Please see board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c + * for details. + */ + printf("88E6185 Initialized\n"); + return 0; } -#endif /* CONFIG_RESET_PHY_R */ diff --git a/board/solidrun/clearfog/MAINTAINERS b/board/solidrun/clearfog/MAINTAINERS new file mode 100644 index 0000000..298e501 --- /dev/null +++ b/board/solidrun/clearfog/MAINTAINERS @@ -0,0 +1,6 @@ +CLEARFOG BOARD +M: Stefan Roese <sr@denx.de> +S: Maintained +F: board/soldrun/clearfog/ +F: include/configs/clearfog.h +F: configs/clearfog_defconfig diff --git a/board/solidrun/clearfog/Makefile b/board/solidrun/clearfog/Makefile new file mode 100644 index 0000000..1920d6b --- /dev/null +++ b/board/solidrun/clearfog/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2015 Stefan Roese <sr@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := clearfog.o diff --git a/board/solidrun/clearfog/README b/board/solidrun/clearfog/README new file mode 100644 index 0000000..2cfa5bf --- /dev/null +++ b/board/solidrun/clearfog/README @@ -0,0 +1,18 @@ +Update from original Marvell U-Boot to mainline U-Boot: +------------------------------------------------------- + +Generate the U-Boot image with these commands: + +$ make clearfog_defconfig +$ make + +The resulting image including the SPL binary with the +full DDR setup is "u-boot-spl.kwb". + +Now all you need to do is copy this image on a SD card. +For example with this command: + +$ sudo dd if=u-boot-spl.kwb of=/dev/sdX bs=512 seek=1 + +Please use the correct device node for your setup instead +of "/dev/sdX" here! diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c new file mode 100644 index 0000000..2773f59 --- /dev/null +++ b/board/solidrun/clearfog/clearfog.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2015 Stefan Roese <sr@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <i2c.h> +#include <miiphy.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/soc.h> + +#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h" +#include <../serdes/a38x/high_speed_env_spec.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define ETH_PHY_CTRL_REG 0 +#define ETH_PHY_CTRL_POWER_DOWN_BIT 11 +#define ETH_PHY_CTRL_POWER_DOWN_MASK (1 << ETH_PHY_CTRL_POWER_DOWN_BIT) + +/* + * Those values and defines are taken from the Marvell U-Boot version + * "u-boot-2013.01-15t1-clearfog" + */ +#define BOARD_GPP_OUT_ENA_LOW 0xffffffff +#define BOARD_GPP_OUT_ENA_MID 0xffffffff + +#define BOARD_GPP_OUT_VAL_LOW 0x0 +#define BOARD_GPP_OUT_VAL_MID 0x0 +#define BOARD_GPP_POL_LOW 0x0 +#define BOARD_GPP_POL_MID 0x0 + +/* IO expander on Marvell GP board includes e.g. fan enabling */ +struct marvell_io_exp { + u8 chip; + u8 addr; + u8 val; +}; + +static struct marvell_io_exp io_exp[] = { + { 0x20, 2, 0x40 }, /* Deassert both mini pcie reset signals */ + { 0x20, 6, 0xf9 }, + { 0x20, 2, 0x46 }, /* rst signals and ena USB3 current limiter */ + { 0x20, 6, 0xb9 }, + { 0x20, 3, 0x00 }, /* Set SFP_TX_DIS to zero */ + { 0x20, 7, 0xbf }, /* Drive SFP_TX_DIS to zero */ +}; + +static struct serdes_map board_serdes_map[] = { + {SATA0, SERDES_SPEED_3_GBPS, SERDES_DEFAULT_MODE, 0, 0}, + {SGMII1, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0}, + {PEX1, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0}, + {USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0}, + {PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0}, + {SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0}, +}; + +int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count) +{ + *serdes_map_array = board_serdes_map; + *count = ARRAY_SIZE(board_serdes_map); + return 0; +} + +/* + * Define the DDR layout / topology here in the board file. This will + * be used by the DDR3 init code in the SPL U-Boot version to configure + * the DDR3 controller. + */ +static struct hws_topology_map board_topology_map = { + 0x1, /* active interfaces */ + /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ + { { { {0x1, 0, 0, 0}, + {0x1, 0, 0, 0}, + {0x1, 0, 0, 0}, + {0x1, 0, 0, 0}, + {0x1, 0, 0, 0} }, + SPEED_BIN_DDR_1600K, /* speed_bin */ + BUS_WIDTH_16, /* memory_width */ + MEM_4G, /* mem_size */ + DDR_FREQ_800, /* frequency */ + 0, 0, /* cas_l cas_wl */ + HWS_TEMP_LOW} }, /* temperature */ + 5, /* Num Of Bus Per Interface*/ + BUS_MASK_32BIT /* Busses mask */ +}; + +struct hws_topology_map *ddr3_get_topology_map(void) +{ + /* Return the board topology as defined in the board code */ + return &board_topology_map; +} + +int board_early_init_f(void) +{ + /* Configure MPP */ + writel(0x11111111, MVEBU_MPP_BASE + 0x00); + writel(0x11111111, MVEBU_MPP_BASE + 0x04); + writel(0x10400011, MVEBU_MPP_BASE + 0x08); + writel(0x22043333, MVEBU_MPP_BASE + 0x0c); + writel(0x44400002, MVEBU_MPP_BASE + 0x10); + writel(0x41144004, MVEBU_MPP_BASE + 0x14); + writel(0x40333333, MVEBU_MPP_BASE + 0x18); + writel(0x00004444, MVEBU_MPP_BASE + 0x1c); + + /* Set GPP Out value */ + writel(BOARD_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00); + writel(BOARD_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00); + + /* Set GPP Polarity */ + writel(BOARD_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c); + writel(BOARD_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c); + + /* Set GPP Out Enable */ + writel(BOARD_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04); + writel(BOARD_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04); + + return 0; +} + +int board_init(void) +{ + int i; + + /* Address of boot parameters */ + gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100; + + /* Toggle GPIO41 to reset onboard switch and phy */ + clrbits_le32(MVEBU_GPIO1_BASE + 0x0, BIT(9)); + clrbits_le32(MVEBU_GPIO1_BASE + 0x4, BIT(9)); + mdelay(1); + setbits_le32(MVEBU_GPIO1_BASE + 0x0, BIT(9)); + mdelay(10); + + /* Init I2C IO expanders */ + for (i = 0; i < ARRAY_SIZE(io_exp); i++) + i2c_write(io_exp[i].chip, io_exp[i].addr, 1, &io_exp[i].val, 1); + + return 0; +} + +int checkboard(void) +{ + puts("Board: SolidRun ClearFog\n"); + + return 0; +} + +int board_eth_init(bd_t *bis) +{ + cpu_eth_init(bis); /* Built in controller(s) come first */ + return pci_eth_init(bis); +} diff --git a/board/solidrun/clearfog/kwbimage.cfg b/board/solidrun/clearfog/kwbimage.cfg new file mode 100644 index 0000000..c650c2c --- /dev/null +++ b/board/solidrun/clearfog/kwbimage.cfg @@ -0,0 +1,12 @@ +# +# Copyright (C) 2015 Stefan Roese <sr@denx.de> +# + +# Armada XP uses version 1 image format +VERSION 1 + +# Boot Media configurations +BOOT_FROM sdio + +# Binary Header (bin_hdr) with DDR3 training code +BINARY spl/u-boot-spl-dtb.bin 0000005b 00000068 diff --git a/configs/clearfog_defconfig b/configs/clearfog_defconfig new file mode 100644 index 0000000..57d6a64 --- /dev/null +++ b/configs/clearfog_defconfig @@ -0,0 +1,21 @@ +CONFIG_ARM=y +CONFIG_ARCH_MVEBU=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_TARGET_CLEARFOG=y +CONFIG_DEFAULT_DEVICE_TREE="armada-388-clearfog" +CONFIG_SPL=y +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_SPL_OF_TRANSLATE=y +CONFIG_SPI_FLASH=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_BASE=0xd0012000 +CONFIG_DEBUG_UART_CLOCK=250000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYS_NS16550=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_STORAGE=y diff --git a/configs/db-88f6820-gp_defconfig b/configs/db-88f6820-gp_defconfig index cdcd34c..111f3a1 100644 --- a/configs/db-88f6820-gp_defconfig +++ b/configs/db-88f6820-gp_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_MVEBU=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_TARGET_DB_88F6820_GP=y CONFIG_DEFAULT_DEVICE_TREE="armada-388-gp" CONFIG_SPL=y @@ -7,9 +8,14 @@ CONFIG_SPL=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set +CONFIG_SPL_OF_TRANSLATE=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_STMICRO=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_BASE=0xd0012000 +CONFIG_DEBUG_UART_CLOCK=250000000 +CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYS_NS16550=y CONFIG_USB=y CONFIG_DM_USB=y diff --git a/configs/db-mv784mp-gp_defconfig b/configs/db-mv784mp-gp_defconfig index 4c4329d..6dda2ae 100644 --- a/configs/db-mv784mp-gp_defconfig +++ b/configs/db-mv784mp-gp_defconfig @@ -1,16 +1,23 @@ CONFIG_ARM=y CONFIG_ARCH_MVEBU=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_TARGET_DB_MV784MP_GP=y CONFIG_DEFAULT_DEVICE_TREE="armada-xp-gp" +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL=y # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set +CONFIG_SPL_OF_TRANSLATE=y CONFIG_NAND_PXA3XX=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_STMICRO=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_BASE=0xd0012000 +CONFIG_DEBUG_UART_CLOCK=250000000 +CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYS_NS16550=y CONFIG_USB=y CONFIG_DM_USB=y diff --git a/configs/ds414_defconfig b/configs/ds414_defconfig new file mode 100644 index 0000000..4c3c1df --- /dev/null +++ b/configs/ds414_defconfig @@ -0,0 +1,18 @@ +CONFIG_ARM=y +CONFIG_ARCH_MVEBU=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_TARGET_DS414=y +CONFIG_DEFAULT_DEVICE_TREE="armada-xp-synology-ds414" +CONFIG_SPL=y +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_SPL_OF_TRANSLATE=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_BAR=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_BASE=0xd0012000 +CONFIG_DEBUG_UART_CLOCK=250000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYS_NS16550=y diff --git a/configs/maxbcm_defconfig b/configs/maxbcm_defconfig index 921c6c4..200c7a0 100644 --- a/configs/maxbcm_defconfig +++ b/configs/maxbcm_defconfig @@ -1,14 +1,20 @@ CONFIG_ARM=y CONFIG_ARCH_MVEBU=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_TARGET_MAXBCM=y -CONFIG_DEFAULT_DEVICE_TREE="armada-xp-gp" +CONFIG_DEFAULT_DEVICE_TREE="armada-xp-maxbcm" CONFIG_SPL=y # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set +CONFIG_SPL_OF_TRANSLATE=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_BASE=0xd0012000 +CONFIG_DEBUG_UART_CLOCK=250000000 +CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYS_NS16550=y diff --git a/drivers/Makefile b/drivers/Makefile index c9031f2..00da40b 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -14,8 +14,8 @@ obj-$(CONFIG_SPL_I2C_SUPPORT) += i2c/ obj-$(CONFIG_SPL_GPIO_SUPPORT) += gpio/ obj-$(CONFIG_SPL_MMC_SUPPORT) += mmc/ obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/ -obj-$(CONFIG_SYS_MVEBU_DDR_A38X) += ddr/marvell/a38x/ -obj-$(CONFIG_SYS_MVEBU_DDR_AXP) += ddr/marvell/axp/ +obj-$(CONFIG_ARMADA_38X) += ddr/marvell/a38x/ +obj-$(CONFIG_ARMADA_XP) += ddr/marvell/axp/ obj-$(CONFIG_ALTERA_SDRAM) += ddr/altera/ obj-$(CONFIG_SPL_SERIAL_SUPPORT) += serial/ obj-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += mtd/spi/ diff --git a/drivers/block/Makefile b/drivers/block/Makefile index f161c01..eb8bda9 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_MVSATA_IDE) += mvsata_ide.o obj-$(CONFIG_MX51_PATA) += mxc_ata.o obj-$(CONFIG_PATA_BFIN) += pata_bfin.o obj-$(CONFIG_SATA_DWC) += sata_dwc.o +obj-$(CONFIG_SATA_MV) += sata_mv.o obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o obj-$(CONFIG_SATA_SIL) += sata_sil.o obj-$(CONFIG_IDE_SIL680) += sil680.o diff --git a/drivers/block/mvsata_ide.c b/drivers/block/mvsata_ide.c index 52c1602..2c6d424 100644 --- a/drivers/block/mvsata_ide.c +++ b/drivers/block/mvsata_ide.c @@ -13,7 +13,7 @@ #include <asm/arch/orion5x.h> #elif defined(CONFIG_KIRKWOOD) #include <asm/arch/soc.h> -#elif defined(CONFIG_ARMADA_XP) +#elif defined(CONFIG_ARCH_MVEBU) #include <linux/mbus.h> #endif @@ -102,7 +102,7 @@ struct mvsata_port_registers { * Initialize SATA memory windows for Armada XP */ -#ifdef CONFIG_ARMADA_XP +#ifdef CONFIG_ARCH_MVEBU static void mvsata_ide_conf_mbus_windows(void) { const struct mbus_dram_target_info *dram; @@ -174,7 +174,7 @@ int ide_preinit(void) int ret = MVSATA_STATUS_TIMEOUT; int status; -#ifdef CONFIG_ARMADA_XP +#ifdef CONFIG_ARCH_MVEBU mvsata_ide_conf_mbus_windows(); #endif diff --git a/drivers/block/sata_mv.c b/drivers/block/sata_mv.c new file mode 100644 index 0000000..8824934 --- /dev/null +++ b/drivers/block/sata_mv.c @@ -0,0 +1,1045 @@ +/* + * Copyright (C) Excito Elektronik i SkÃ¥ne AB, 2010. + * Author: Tor Krill <tor@excito.com> + * + * Copyright (C) 2015 Stefan Roese <sr@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * This driver supports the SATA controller of some Mavell SoC's. + * Here a (most likely incomplete) list of the supported SoC's: + * - Kirkwood + * - Armada 370 + * - Armada XP + * + * This driver implementation is an alternative to the already available + * driver via the "ide" commands interface (drivers/block/mvsata_ide.c). + * But this driver only supports PIO mode and as this new driver also + * supports transfer via DMA, its much faster. + * + * Please note, that the newer SoC's (e.g. Armada 38x) are not supported + * by this driver. As they have an AHCI compatible SATA controller + * integrated. + */ + +/* + * TODO: + * Better error recovery + * No support for using PRDs (Thus max 64KB transfers) + * No NCQ support + * No port multiplier support + */ + +#include <common.h> +#include <fis.h> +#include <libata.h> +#include <malloc.h> +#include <sata.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <linux/mbus.h> + +#if defined(CONFIG_KIRKWOOD) +#include <asm/arch/kirkwood.h> +#define SATAHC_BASE KW_SATA_BASE +#else +#include <asm/arch/soc.h> +#define SATAHC_BASE MVEBU_AXP_SATA_BASE +#endif + +#define SATA0_BASE (SATAHC_BASE + 0x2000) +#define SATA1_BASE (SATAHC_BASE + 0x4000) + +/* EDMA registers */ +#define EDMA_CFG 0x000 +#define EDMA_CFG_NCQ (1 << 5) +#define EDMA_CFG_EQUE (1 << 9) +#define EDMA_TIMER 0x004 +#define EDMA_IECR 0x008 +#define EDMA_IEMR 0x00c +#define EDMA_RQBA_HI 0x010 +#define EDMA_RQIPR 0x014 +#define EDMA_RQIPR_IPMASK (0x1f << 5) +#define EDMA_RQIPR_IPSHIFT 5 +#define EDMA_RQOPR 0x018 +#define EDMA_RQOPR_OPMASK (0x1f << 5) +#define EDMA_RQOPR_OPSHIFT 5 +#define EDMA_RSBA_HI 0x01c +#define EDMA_RSIPR 0x020 +#define EDMA_RSIPR_IPMASK (0x1f << 3) +#define EDMA_RSIPR_IPSHIFT 3 +#define EDMA_RSOPR 0x024 +#define EDMA_RSOPR_OPMASK (0x1f << 3) +#define EDMA_RSOPR_OPSHIFT 3 +#define EDMA_CMD 0x028 +#define EDMA_CMD_ENEDMA (0x01 << 0) +#define EDMA_CMD_DISEDMA (0x01 << 1) +#define EDMA_CMD_ATARST (0x01 << 2) +#define EDMA_CMD_FREEZE (0x01 << 4) +#define EDMA_TEST_CTL 0x02c +#define EDMA_STATUS 0x030 +#define EDMA_IORTO 0x034 +#define EDMA_CDTR 0x040 +#define EDMA_HLTCND 0x060 +#define EDMA_NTSR 0x094 + +/* Basic DMA registers */ +#define BDMA_CMD 0x224 +#define BDMA_STATUS 0x228 +#define BDMA_DTLB 0x22c +#define BDMA_DTHB 0x230 +#define BDMA_DRL 0x234 +#define BDMA_DRH 0x238 + +/* SATA Interface registers */ +#define SIR_ICFG 0x050 +#define SIR_CFG_GEN2EN (0x1 << 7) +#define SIR_PLL_CFG 0x054 +#define SIR_SSTATUS 0x300 +#define SSTATUS_DET_MASK (0x0f << 0) +#define SIR_SERROR 0x304 +#define SIR_SCONTROL 0x308 +#define SIR_SCONTROL_DETEN (0x01 << 0) +#define SIR_LTMODE 0x30c +#define SIR_LTMODE_NELBE (0x01 << 7) +#define SIR_PHYMODE3 0x310 +#define SIR_PHYMODE4 0x314 +#define SIR_PHYMODE1 0x32c +#define SIR_PHYMODE2 0x330 +#define SIR_BIST_CTRL 0x334 +#define SIR_BIST_DW1 0x338 +#define SIR_BIST_DW2 0x33c +#define SIR_SERR_IRQ_MASK 0x340 +#define SIR_SATA_IFCTRL 0x344 +#define SIR_SATA_TESTCTRL 0x348 +#define SIR_SATA_IFSTATUS 0x34c +#define SIR_VEND_UNIQ 0x35c +#define SIR_FIS_CFG 0x360 +#define SIR_FIS_IRQ_CAUSE 0x364 +#define SIR_FIS_IRQ_MASK 0x368 +#define SIR_FIS_DWORD0 0x370 +#define SIR_FIS_DWORD1 0x374 +#define SIR_FIS_DWORD2 0x378 +#define SIR_FIS_DWORD3 0x37c +#define SIR_FIS_DWORD4 0x380 +#define SIR_FIS_DWORD5 0x384 +#define SIR_FIS_DWORD6 0x388 +#define SIR_PHYM9_GEN2 0x398 +#define SIR_PHYM9_GEN1 0x39c +#define SIR_PHY_CFG 0x3a0 +#define SIR_PHYCTL 0x3a4 +#define SIR_PHYM10 0x3a8 +#define SIR_PHYM12 0x3b0 + +/* Shadow registers */ +#define PIO_DATA 0x100 +#define PIO_ERR_FEATURES 0x104 +#define PIO_SECTOR_COUNT 0x108 +#define PIO_LBA_LOW 0x10c +#define PIO_LBA_MID 0x110 +#define PIO_LBA_HI 0x114 +#define PIO_DEVICE 0x118 +#define PIO_CMD_STATUS 0x11c +#define PIO_STATUS_ERR (0x01 << 0) +#define PIO_STATUS_DRQ (0x01 << 3) +#define PIO_STATUS_DF (0x01 << 5) +#define PIO_STATUS_DRDY (0x01 << 6) +#define PIO_STATUS_BSY (0x01 << 7) +#define PIO_CTRL_ALTSTAT 0x120 + +/* SATAHC arbiter registers */ +#define SATAHC_CFG 0x000 +#define SATAHC_RQOP 0x004 +#define SATAHC_RQIP 0x008 +#define SATAHC_ICT 0x00c +#define SATAHC_ITT 0x010 +#define SATAHC_ICR 0x014 +#define SATAHC_ICR_PORT0 (0x01 << 0) +#define SATAHC_ICR_PORT1 (0x01 << 1) +#define SATAHC_MIC 0x020 +#define SATAHC_MIM 0x024 +#define SATAHC_LED_CFG 0x02c + +#define REQUEST_QUEUE_SIZE 32 +#define RESPONSE_QUEUE_SIZE REQUEST_QUEUE_SIZE + +struct crqb { + u32 dtb_low; /* DW0 */ + u32 dtb_high; /* DW1 */ + u32 control_flags; /* DW2 */ + u32 drb_count; /* DW3 */ + u32 ata_cmd_feat; /* DW4 */ + u32 ata_addr; /* DW5 */ + u32 ata_addr_exp; /* DW6 */ + u32 ata_sect_count; /* DW7 */ +}; + +#define CRQB_ALIGN 0x400 + +#define CRQB_CNTRLFLAGS_DIR (0x01 << 0) +#define CRQB_CNTRLFLAGS_DQTAGMASK (0x1f << 1) +#define CRQB_CNTRLFLAGS_DQTAGSHIFT 1 +#define CRQB_CNTRLFLAGS_PMPORTMASK (0x0f << 12) +#define CRQB_CNTRLFLAGS_PMPORTSHIFT 12 +#define CRQB_CNTRLFLAGS_PRDMODE (0x01 << 16) +#define CRQB_CNTRLFLAGS_HQTAGMASK (0x1f << 17) +#define CRQB_CNTRLFLAGS_HQTAGSHIFT 17 + +#define CRQB_CMDFEAT_CMDMASK (0xff << 16) +#define CRQB_CMDFEAT_CMDSHIFT 16 +#define CRQB_CMDFEAT_FEATMASK (0xff << 16) +#define CRQB_CMDFEAT_FEATSHIFT 24 + +#define CRQB_ADDR_LBA_LOWMASK (0xff << 0) +#define CRQB_ADDR_LBA_LOWSHIFT 0 +#define CRQB_ADDR_LBA_MIDMASK (0xff << 8) +#define CRQB_ADDR_LBA_MIDSHIFT 8 +#define CRQB_ADDR_LBA_HIGHMASK (0xff << 16) +#define CRQB_ADDR_LBA_HIGHSHIFT 16 +#define CRQB_ADDR_DEVICE_MASK (0xff << 24) +#define CRQB_ADDR_DEVICE_SHIFT 24 + +#define CRQB_ADDR_LBA_LOW_EXP_MASK (0xff << 0) +#define CRQB_ADDR_LBA_LOW_EXP_SHIFT 0 +#define CRQB_ADDR_LBA_MID_EXP_MASK (0xff << 8) +#define CRQB_ADDR_LBA_MID_EXP_SHIFT 8 +#define CRQB_ADDR_LBA_HIGH_EXP_MASK (0xff << 16) +#define CRQB_ADDR_LBA_HIGH_EXP_SHIFT 16 +#define CRQB_ADDR_FEATURE_EXP_MASK (0xff << 24) +#define CRQB_ADDR_FEATURE_EXP_SHIFT 24 + +#define CRQB_SECTCOUNT_COUNT_MASK (0xff << 0) +#define CRQB_SECTCOUNT_COUNT_SHIFT 0 +#define CRQB_SECTCOUNT_COUNT_EXP_MASK (0xff << 8) +#define CRQB_SECTCOUNT_COUNT_EXP_SHIFT 8 + +#define MVSATA_WIN_CONTROL(w) (MVEBU_AXP_SATA_BASE + 0x30 + ((w) << 4)) +#define MVSATA_WIN_BASE(w) (MVEBU_AXP_SATA_BASE + 0x34 + ((w) << 4)) + +struct eprd { + u32 phyaddr_low; + u32 bytecount_eot; + u32 phyaddr_hi; + u32 reserved; +}; + +#define EPRD_PHYADDR_MASK 0xfffffffe +#define EPRD_BYTECOUNT_MASK 0x0000ffff +#define EPRD_EOT (0x01 << 31) + +struct crpb { + u32 id; + u32 flags; + u32 timestamp; +}; + +#define CRPB_ALIGN 0x100 + +#define READ_CMD 0 +#define WRITE_CMD 1 + +/* + * Since we don't use PRDs yet max transfer size + * is 64KB + */ +#define MV_ATA_MAX_SECTORS (65535 / ATA_SECT_SIZE) + +/* Keep track if hw is initialized or not */ +static u32 hw_init; + +struct mv_priv { + char name[12]; + u32 link; + u32 regbase; + u32 queue_depth; + u16 pio; + u16 mwdma; + u16 udma; + + void *crqb_alloc; + struct crqb *request; + + void *crpb_alloc; + struct crpb *response; +}; + +static int ata_wait_register(u32 *addr, u32 mask, u32 val, u32 timeout_msec) +{ + ulong start; + + start = get_timer(0); + do { + if ((in_le32(addr) & mask) == val) + return 0; + } while (get_timer(start) < timeout_msec); + + return -ETIMEDOUT; +} + +/* Cut from sata_mv in linux kernel */ +static int mv_stop_edma_engine(int port) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + int i; + + /* Disable eDMA. The disable bit auto clears. */ + out_le32(priv->regbase + EDMA_CMD, EDMA_CMD_DISEDMA); + + /* Wait for the chip to confirm eDMA is off. */ + for (i = 10000; i > 0; i--) { + u32 reg = in_le32(priv->regbase + EDMA_CMD); + if (!(reg & EDMA_CMD_ENEDMA)) { + debug("EDMA stop on port %d succesful\n", port); + return 0; + } + udelay(10); + } + debug("EDMA stop on port %d failed\n", port); + return -1; +} + +static int mv_start_edma_engine(int port) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + u32 tmp; + + /* Check preconditions */ + tmp = in_le32(priv->regbase + SIR_SSTATUS); + if ((tmp & SSTATUS_DET_MASK) != 0x03) { + printf("Device error on port: %d\n", port); + return -1; + } + + tmp = in_le32(priv->regbase + PIO_CMD_STATUS); + if (tmp & (ATA_BUSY | ATA_DRQ)) { + printf("Device not ready on port: %d\n", port); + return -1; + } + + /* Clear interrupt cause */ + out_le32(priv->regbase + EDMA_IECR, 0x0); + + tmp = in_le32(SATAHC_BASE + SATAHC_ICR); + tmp &= ~(port == 0 ? SATAHC_ICR_PORT0 : SATAHC_ICR_PORT1); + out_le32(SATAHC_BASE + SATAHC_ICR, tmp); + + /* Configure edma operation */ + tmp = in_le32(priv->regbase + EDMA_CFG); + tmp &= ~EDMA_CFG_NCQ; /* No NCQ */ + tmp &= ~EDMA_CFG_EQUE; /* Dont queue operations */ + out_le32(priv->regbase + EDMA_CFG, tmp); + + out_le32(priv->regbase + SIR_FIS_IRQ_CAUSE, 0x0); + + /* Configure fis, set all to no-wait for now */ + out_le32(priv->regbase + SIR_FIS_CFG, 0x0); + + /* Setup request queue */ + out_le32(priv->regbase + EDMA_RQBA_HI, 0x0); + out_le32(priv->regbase + EDMA_RQIPR, priv->request); + out_le32(priv->regbase + EDMA_RQOPR, 0x0); + + /* Setup response queue */ + out_le32(priv->regbase + EDMA_RSBA_HI, 0x0); + out_le32(priv->regbase + EDMA_RSOPR, priv->response); + out_le32(priv->regbase + EDMA_RSIPR, 0x0); + + /* Start edma */ + out_le32(priv->regbase + EDMA_CMD, EDMA_CMD_ENEDMA); + + return 0; +} + +static int mv_reset_channel(int port) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + + /* Make sure edma is stopped */ + mv_stop_edma_engine(port); + + out_le32(priv->regbase + EDMA_CMD, EDMA_CMD_ATARST); + udelay(25); /* allow reset propagation */ + out_le32(priv->regbase + EDMA_CMD, 0); + mdelay(10); + + return 0; +} + +static void mv_reset_port(int port) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + + mv_reset_channel(port); + + out_le32(priv->regbase + EDMA_CMD, 0x0); + out_le32(priv->regbase + EDMA_CFG, 0x101f); + out_le32(priv->regbase + EDMA_IECR, 0x0); + out_le32(priv->regbase + EDMA_IEMR, 0x0); + out_le32(priv->regbase + EDMA_RQBA_HI, 0x0); + out_le32(priv->regbase + EDMA_RQIPR, 0x0); + out_le32(priv->regbase + EDMA_RQOPR, 0x0); + out_le32(priv->regbase + EDMA_RSBA_HI, 0x0); + out_le32(priv->regbase + EDMA_RSIPR, 0x0); + out_le32(priv->regbase + EDMA_RSOPR, 0x0); + out_le32(priv->regbase + EDMA_IORTO, 0xfa); +} + +static void mv_reset_one_hc(void) +{ + out_le32(SATAHC_BASE + SATAHC_ICT, 0x00); + out_le32(SATAHC_BASE + SATAHC_ITT, 0x00); + out_le32(SATAHC_BASE + SATAHC_ICR, 0x00); +} + +static int probe_port(int port) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + int tries, tries2, set15 = 0; + u32 tmp; + + debug("Probe port: %d\n", port); + + for (tries = 0; tries < 2; tries++) { + /* Clear SError */ + out_le32(priv->regbase + SIR_SERROR, 0x0); + + /* trigger com-init */ + tmp = in_le32(priv->regbase + SIR_SCONTROL); + tmp = (tmp & 0x0f0) | 0x300 | SIR_SCONTROL_DETEN; + out_le32(priv->regbase + SIR_SCONTROL, tmp); + + mdelay(1); + + tmp = in_le32(priv->regbase + SIR_SCONTROL); + tries2 = 5; + do { + tmp = (tmp & 0x0f0) | 0x300; + out_le32(priv->regbase + SIR_SCONTROL, tmp); + mdelay(10); + tmp = in_le32(priv->regbase + SIR_SCONTROL); + } while ((tmp & 0xf0f) != 0x300 && tries2--); + + mdelay(10); + + for (tries2 = 0; tries2 < 200; tries2++) { + tmp = in_le32(priv->regbase + SIR_SSTATUS); + if ((tmp & SSTATUS_DET_MASK) == 0x03) { + debug("Found device on port\n"); + return 0; + } + mdelay(1); + } + + if ((tmp & SSTATUS_DET_MASK) == 0) { + debug("No device attached on port %d\n", port); + return -ENODEV; + } + + if (!set15) { + /* Try on 1.5Gb/S */ + debug("Try 1.5Gb link\n"); + set15 = 1; + out_le32(priv->regbase + SIR_SCONTROL, 0x304); + + tmp = in_le32(priv->regbase + SIR_ICFG); + tmp &= ~SIR_CFG_GEN2EN; + out_le32(priv->regbase + SIR_ICFG, tmp); + + mv_reset_channel(port); + } + } + + debug("Failed to probe port\n"); + return -1; +} + +/* Get request queue in pointer */ +static int get_reqip(int port) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + u32 tmp; + + tmp = in_le32(priv->regbase + EDMA_RQIPR) & EDMA_RQIPR_IPMASK; + tmp = tmp >> EDMA_RQIPR_IPSHIFT; + + return tmp; +} + +static void set_reqip(int port, int reqin) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + u32 tmp; + + tmp = in_le32(priv->regbase + EDMA_RQIPR) & ~EDMA_RQIPR_IPMASK; + tmp |= ((reqin << EDMA_RQIPR_IPSHIFT) & EDMA_RQIPR_IPMASK); + out_le32(priv->regbase + EDMA_RQIPR, tmp); +} + +/* Get next available slot, ignoring possible overwrite */ +static int get_next_reqip(int port) +{ + int slot = get_reqip(port); + slot = (slot + 1) % REQUEST_QUEUE_SIZE; + return slot; +} + +/* Get response queue in pointer */ +static int get_rspip(int port) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + u32 tmp; + + tmp = in_le32(priv->regbase + EDMA_RSIPR) & EDMA_RSIPR_IPMASK; + tmp = tmp >> EDMA_RSIPR_IPSHIFT; + + return tmp; +} + +/* Get response queue out pointer */ +static int get_rspop(int port) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + u32 tmp; + + tmp = in_le32(priv->regbase + EDMA_RSOPR) & EDMA_RSOPR_OPMASK; + tmp = tmp >> EDMA_RSOPR_OPSHIFT; + return tmp; +} + +/* Get next response queue pointer */ +static int get_next_rspop(int port) +{ + return (get_rspop(port) + 1) % RESPONSE_QUEUE_SIZE; +} + +/* Set response queue pointer */ +static void set_rspop(int port, int reqin) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + u32 tmp; + + tmp = in_le32(priv->regbase + EDMA_RSOPR) & ~EDMA_RSOPR_OPMASK; + tmp |= ((reqin << EDMA_RSOPR_OPSHIFT) & EDMA_RSOPR_OPMASK); + + out_le32(priv->regbase + EDMA_RSOPR, tmp); +} + +static int wait_dma_completion(int port, int index, u32 timeout_msec) +{ + u32 tmp, res; + + tmp = port == 0 ? SATAHC_ICR_PORT0 : SATAHC_ICR_PORT1; + res = ata_wait_register((u32 *)(SATAHC_BASE + SATAHC_ICR), tmp, + tmp, timeout_msec); + if (res) + printf("Failed to wait for completion on port %d\n", port); + + return res; +} + +static void process_responses(int port) +{ +#ifdef DEBUG + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; +#endif + u32 tmp; + u32 outind = get_rspop(port); + + /* Ack interrupts */ + tmp = in_le32(SATAHC_BASE + SATAHC_ICR); + if (port == 0) + tmp &= ~(BIT(0) | BIT(8)); + else + tmp &= ~(BIT(1) | BIT(9)); + tmp &= ~(BIT(4)); + out_le32(SATAHC_BASE + SATAHC_ICR, tmp); + + while (get_rspip(port) != outind) { +#ifdef DEBUG + debug("Response index %d flags %08x on port %d\n", outind, + priv->response[outind].flags, port); +#endif + outind = get_next_rspop(port); + set_rspop(port, outind); + } +} + +static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, + u8 *buffer, u32 len, u32 iswrite) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct crqb *req; + int slot; + + if (len >= 64 * 1024) { + printf("We only support <64K transfers for now\n"); + return -1; + } + + /* Initialize request */ + slot = get_reqip(port); + memset(&priv->request[slot], 0, sizeof(struct crqb)); + req = &priv->request[slot]; + + req->dtb_low = (u32)buffer; + + /* Dont use PRDs */ + req->control_flags = CRQB_CNTRLFLAGS_PRDMODE; + req->control_flags |= iswrite ? 0 : CRQB_CNTRLFLAGS_DIR; + req->control_flags |= + ((cfis->pm_port_c << CRQB_CNTRLFLAGS_PMPORTSHIFT) + & CRQB_CNTRLFLAGS_PMPORTMASK); + + req->drb_count = len; + + req->ata_cmd_feat = (cfis->command << CRQB_CMDFEAT_CMDSHIFT) & + CRQB_CMDFEAT_CMDMASK; + req->ata_cmd_feat |= (cfis->features << CRQB_CMDFEAT_FEATSHIFT) & + CRQB_CMDFEAT_FEATMASK; + + req->ata_addr = (cfis->lba_low << CRQB_ADDR_LBA_LOWSHIFT) & + CRQB_ADDR_LBA_LOWMASK; + req->ata_addr |= (cfis->lba_mid << CRQB_ADDR_LBA_MIDSHIFT) & + CRQB_ADDR_LBA_MIDMASK; + req->ata_addr |= (cfis->lba_high << CRQB_ADDR_LBA_HIGHSHIFT) & + CRQB_ADDR_LBA_HIGHMASK; + req->ata_addr |= (cfis->device << CRQB_ADDR_DEVICE_SHIFT) & + CRQB_ADDR_DEVICE_MASK; + + req->ata_addr_exp = (cfis->lba_low_exp << CRQB_ADDR_LBA_LOW_EXP_SHIFT) & + CRQB_ADDR_LBA_LOW_EXP_MASK; + req->ata_addr_exp |= + (cfis->lba_mid_exp << CRQB_ADDR_LBA_MID_EXP_SHIFT) & + CRQB_ADDR_LBA_MID_EXP_MASK; + req->ata_addr_exp |= + (cfis->lba_high_exp << CRQB_ADDR_LBA_HIGH_EXP_SHIFT) & + CRQB_ADDR_LBA_HIGH_EXP_MASK; + req->ata_addr_exp |= + (cfis->features_exp << CRQB_ADDR_FEATURE_EXP_SHIFT) & + CRQB_ADDR_FEATURE_EXP_MASK; + + req->ata_sect_count = + (cfis->sector_count << CRQB_SECTCOUNT_COUNT_SHIFT) & + CRQB_SECTCOUNT_COUNT_MASK; + req->ata_sect_count |= + (cfis->sector_count_exp << CRQB_SECTCOUNT_COUNT_EXP_SHIFT) & + CRQB_SECTCOUNT_COUNT_EXP_MASK; + + /* Flush data */ + flush_dcache_range((u32)req, (u32)req + sizeof(*req)); + + /* Trigger operation */ + slot = get_next_reqip(port); + set_reqip(port, slot); + + /* Wait for completion */ + if (wait_dma_completion(port, slot, 10000)) { + printf("ATA operation timed out\n"); + return -1; + } + + process_responses(port); + + /* Invalidate data on read */ + if (buffer && len) + invalidate_dcache_range((u32)buffer, (u32)buffer + len); + + return len; +} + +static u32 mv_sata_rw_cmd_ext(int port, lbaint_t start, u32 blkcnt, + u8 *buffer, int is_write) +{ + struct sata_fis_h2d cfis; + u32 res; + u64 block; + + block = (u64)start; + + memset(&cfis, 0, sizeof(struct sata_fis_h2d)); + + cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D; + cfis.command = (is_write) ? ATA_CMD_WRITE_EXT : ATA_CMD_READ_EXT; + + cfis.lba_high_exp = (block >> 40) & 0xff; + cfis.lba_mid_exp = (block >> 32) & 0xff; + cfis.lba_low_exp = (block >> 24) & 0xff; + cfis.lba_high = (block >> 16) & 0xff; + cfis.lba_mid = (block >> 8) & 0xff; + cfis.lba_low = block & 0xff; + cfis.device = ATA_LBA; + cfis.sector_count_exp = (blkcnt >> 8) & 0xff; + cfis.sector_count = blkcnt & 0xff; + + res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt, + is_write); + + return res >= 0 ? blkcnt : res; +} + +static u32 mv_sata_rw_cmd(int port, lbaint_t start, u32 blkcnt, u8 *buffer, + int is_write) +{ + struct sata_fis_h2d cfis; + lbaint_t block; + u32 res; + + block = start; + + memset(&cfis, 0, sizeof(struct sata_fis_h2d)); + + cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D; + cfis.command = (is_write) ? ATA_CMD_WRITE : ATA_CMD_READ; + cfis.device = ATA_LBA; + + cfis.device |= (block >> 24) & 0xf; + cfis.lba_high = (block >> 16) & 0xff; + cfis.lba_mid = (block >> 8) & 0xff; + cfis.lba_low = block & 0xff; + cfis.sector_count = (u8)(blkcnt & 0xff); + + res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt, + is_write); + + return res >= 0 ? blkcnt : res; +} + +static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer, int is_write) +{ + lbaint_t start, blks; + u8 *addr; + int max_blks; + + debug("%s: %ld %ld\n", __func__, blknr, blkcnt); + + start = blknr; + blks = blkcnt; + addr = (u8 *)buffer; + + max_blks = MV_ATA_MAX_SECTORS; + do { + if (blks > max_blks) { + if (sata_dev_desc[dev].lba48) { + mv_sata_rw_cmd_ext(dev, start, max_blks, addr, + is_write); + } else { + mv_sata_rw_cmd(dev, start, max_blks, addr, + is_write); + } + start += max_blks; + blks -= max_blks; + addr += ATA_SECT_SIZE * max_blks; + } else { + if (sata_dev_desc[dev].lba48) { + mv_sata_rw_cmd_ext(dev, start, blks, addr, + is_write); + } else { + mv_sata_rw_cmd(dev, start, blks, addr, + is_write); + } + start += blks; + blks = 0; + addr += ATA_SECT_SIZE * blks; + } + } while (blks != 0); + + return blkcnt; +} + +static int mv_ata_exec_ata_cmd_nondma(int port, + struct sata_fis_h2d *cfis, u8 *buffer, + u32 len, u32 iswrite) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + int i; + u16 *tp; + + debug("%s\n", __func__); + + out_le32(priv->regbase + PIO_SECTOR_COUNT, cfis->sector_count); + out_le32(priv->regbase + PIO_LBA_HI, cfis->lba_high); + out_le32(priv->regbase + PIO_LBA_MID, cfis->lba_mid); + out_le32(priv->regbase + PIO_LBA_LOW, cfis->lba_low); + out_le32(priv->regbase + PIO_ERR_FEATURES, cfis->features); + out_le32(priv->regbase + PIO_DEVICE, cfis->device); + out_le32(priv->regbase + PIO_CMD_STATUS, cfis->command); + + if (ata_wait_register((u32 *)(priv->regbase + PIO_CMD_STATUS), + ATA_BUSY, 0x0, 10000)) { + debug("Failed to wait for completion\n"); + return -1; + } + + if (len > 0) { + tp = (u16 *)buffer; + for (i = 0; i < len / 2; i++) { + if (iswrite) + out_le16(priv->regbase + PIO_DATA, *tp++); + else + *tp++ = in_le16(priv->regbase + PIO_DATA); + } + } + + return len; +} + +static int mv_sata_identify(int port, u16 *id) +{ + struct sata_fis_h2d h2d; + + memset(&h2d, 0, sizeof(struct sata_fis_h2d)); + + h2d.fis_type = SATA_FIS_TYPE_REGISTER_H2D; + h2d.command = ATA_CMD_ID_ATA; + + /* Give device time to get operational */ + mdelay(10); + + return mv_ata_exec_ata_cmd_nondma(port, &h2d, (u8 *)id, + ATA_ID_WORDS * 2, READ_CMD); +} + +static void mv_sata_xfer_mode(int port, u16 *id) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + + priv->pio = id[ATA_ID_PIO_MODES]; + priv->mwdma = id[ATA_ID_MWDMA_MODES]; + priv->udma = id[ATA_ID_UDMA_MODES]; + debug("pio %04x, mwdma %04x, udma %04x\n", priv->pio, priv->mwdma, + priv->udma); +} + +static void mv_sata_set_features(int port) +{ + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct sata_fis_h2d cfis; + u8 udma_cap; + + memset(&cfis, 0, sizeof(struct sata_fis_h2d)); + + cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D; + cfis.command = ATA_CMD_SET_FEATURES; + cfis.features = SETFEATURES_XFER; + + /* First check the device capablity */ + udma_cap = (u8) (priv->udma & 0xff); + + if (udma_cap == ATA_UDMA6) + cfis.sector_count = XFER_UDMA_6; + if (udma_cap == ATA_UDMA5) + cfis.sector_count = XFER_UDMA_5; + if (udma_cap == ATA_UDMA4) + cfis.sector_count = XFER_UDMA_4; + if (udma_cap == ATA_UDMA3) + cfis.sector_count = XFER_UDMA_3; + + mv_ata_exec_ata_cmd_nondma(port, &cfis, NULL, 0, READ_CMD); +} + +int mv_sata_spin_down(int dev) +{ + struct sata_fis_h2d cfis; + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv; + + if (priv->link == 0) { + debug("No device on port: %d\n", dev); + return 1; + } + + memset(&cfis, 0, sizeof(struct sata_fis_h2d)); + + cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D; + cfis.command = ATA_CMD_STANDBY; + + return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD); +} + +int mv_sata_spin_up(int dev) +{ + struct sata_fis_h2d cfis; + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv; + + if (priv->link == 0) { + debug("No device on port: %d\n", dev); + return 1; + } + + memset(&cfis, 0, sizeof(struct sata_fis_h2d)); + + cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D; + cfis.command = ATA_CMD_IDLE; + + return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD); +} + +ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer) +{ + return ata_low_level_rw(dev, blknr, blkcnt, buffer, READ_CMD); +} + +ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer) +{ + return ata_low_level_rw(dev, blknr, blkcnt, (void *)buffer, WRITE_CMD); +} + +/* + * Initialize SATA memory windows + */ +static void mvsata_ide_conf_mbus_windows(void) +{ + const struct mbus_dram_target_info *dram; + int i; + + dram = mvebu_mbus_dram_info(); + + /* Disable windows, Set Size/Base to 0 */ + for (i = 0; i < 4; i++) { + writel(0, MVSATA_WIN_CONTROL(i)); + writel(0, MVSATA_WIN_BASE(i)); + } + + for (i = 0; i < dram->num_cs; i++) { + const struct mbus_dram_window *cs = dram->cs + i; + writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) | + (dram->mbus_dram_target_id << 4) | 1, + MVSATA_WIN_CONTROL(i)); + writel(cs->base & 0xffff0000, MVSATA_WIN_BASE(i)); + } +} + +int init_sata(int dev) +{ + struct mv_priv *priv; + + debug("Initialize sata dev: %d\n", dev); + + if (dev < 0 || dev >= CONFIG_SYS_SATA_MAX_DEVICE) { + printf("Invalid sata device %d\n", dev); + return -1; + } + + priv = (struct mv_priv *)malloc(sizeof(struct mv_priv)); + if (!priv) { + printf("Failed to allocate memory for private sata data\n"); + return -ENOMEM; + } + + memset((void *)priv, 0, sizeof(struct mv_priv)); + + /* Allocate and align request buffer */ + priv->crqb_alloc = malloc(sizeof(struct crqb) * REQUEST_QUEUE_SIZE + + CRQB_ALIGN); + if (!priv->crqb_alloc) { + printf("Unable to allocate memory for request queue\n"); + return -ENOMEM; + } + memset(priv->crqb_alloc, 0, + sizeof(struct crqb) * REQUEST_QUEUE_SIZE + CRQB_ALIGN); + priv->request = (struct crqb *)(((u32) priv->crqb_alloc + CRQB_ALIGN) & + ~(CRQB_ALIGN - 1)); + + /* Allocate and align response buffer */ + priv->crpb_alloc = malloc(sizeof(struct crpb) * REQUEST_QUEUE_SIZE + + CRPB_ALIGN); + if (!priv->crpb_alloc) { + printf("Unable to allocate memory for response queue\n"); + return -ENOMEM; + } + memset(priv->crpb_alloc, 0, + sizeof(struct crpb) * REQUEST_QUEUE_SIZE + CRPB_ALIGN); + priv->response = (struct crpb *)(((u32) priv->crpb_alloc + CRPB_ALIGN) & + ~(CRPB_ALIGN - 1)); + + sata_dev_desc[dev].priv = (void *)priv; + + sprintf(priv->name, "SATA%d", dev); + + priv->regbase = dev == 0 ? SATA0_BASE : SATA1_BASE; + + if (!hw_init) { + debug("Initialize sata hw\n"); + hw_init = 1; + mv_reset_one_hc(); + mvsata_ide_conf_mbus_windows(); + } + + mv_reset_port(dev); + + if (probe_port(dev)) { + priv->link = 0; + return -ENODEV; + } + priv->link = 1; + + return 0; +} + +int reset_sata(int dev) +{ + return 0; +} + +int scan_sata(int port) +{ + unsigned char serial[ATA_ID_SERNO_LEN + 1]; + unsigned char firmware[ATA_ID_FW_REV_LEN + 1]; + unsigned char product[ATA_ID_PROD_LEN + 1]; + u64 n_sectors; + u16 *id; + struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + + if (!priv->link) + return -ENODEV; + + id = (u16 *)malloc(ATA_ID_WORDS * 2); + if (!id) { + printf("Failed to malloc id data\n"); + return -ENOMEM; + } + + mv_sata_identify(port, id); + ata_swap_buf_le16(id, ATA_ID_WORDS); +#ifdef DEBUG + ata_dump_id(id); +#endif + + /* Serial number */ + ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial)); + memcpy(sata_dev_desc[port].product, serial, sizeof(serial)); + + /* Firmware version */ + ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware)); + memcpy(sata_dev_desc[port].revision, firmware, sizeof(firmware)); + + /* Product model */ + ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product)); + memcpy(sata_dev_desc[port].vendor, product, sizeof(product)); + + /* Total sectors */ + n_sectors = ata_id_n_sectors(id); + sata_dev_desc[port].lba = n_sectors; + + /* Check if support LBA48 */ + if (ata_id_has_lba48(id)) { + sata_dev_desc[port].lba48 = 1; + debug("Device support LBA48\n"); + } + + /* Get the NCQ queue depth from device */ + priv->queue_depth = ata_id_queue_depth(id); + + /* Get the xfer mode from device */ + mv_sata_xfer_mode(port, id); + + /* Set the xfer mode to highest speed */ + mv_sata_set_features(port); + + /* Start up */ + mv_start_edma_engine(port); + + return 0; +} diff --git a/drivers/ddr/marvell/a38x/ddr3_debug.c b/drivers/ddr/marvell/a38x/ddr3_debug.c index 1d72bc5..12b5b04 100644 --- a/drivers/ddr/marvell/a38x/ddr3_debug.c +++ b/drivers/ddr/marvell/a38x/ddr3_debug.c @@ -165,21 +165,6 @@ int ddr3_tip_init_config_func(u32 dev_num, } /* - * Read training result table - */ -int hws_ddr3_tip_read_training_result( - u32 dev_num, enum hws_result result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]) -{ - dev_num = dev_num; - - if (result == NULL) - return MV_BAD_PARAM; - memcpy(result, training_result, sizeof(result)); - - return MV_OK; -} - -/* * Get training result info pointer */ enum hws_result *ddr3_tip_get_result_ptr(u32 stage) diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip.h b/drivers/ddr/marvell/a38x/ddr3_training_ip.h index 76a1b6a0..ed92873 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip.h @@ -171,8 +171,6 @@ int hws_ddr3_tip_load_topology_map(u32 dev_num, struct hws_topology_map *topology); int hws_ddr3_tip_run_alg(u32 dev_num, enum hws_algo_type algo_type); int hws_ddr3_tip_mode_read(u32 dev_num, struct mode_info *mode_info); -int hws_ddr3_tip_read_training_result(u32 dev_num, - enum hws_result result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]); int ddr3_tip_is_pup_lock(u32 *pup_buf, enum hws_training_result read_mode); u8 ddr3_tip_get_buf_min(u8 *buf_ptr); u8 ddr3_tip_get_buf_max(u8 *buf_ptr); diff --git a/drivers/ddr/marvell/axp/ddr3_axp.h b/drivers/ddr/marvell/axp/ddr3_axp.h index d9e33f7..75d315a 100644 --- a/drivers/ddr/marvell/axp/ddr3_axp.h +++ b/drivers/ddr/marvell/axp/ddr3_axp.h @@ -33,7 +33,10 @@ #define SAR1_CPU_CORE_MASK 0x00000018 #define SAR1_CPU_CORE_OFFSET 3 +/* Only enable ECC if the board selects it */ +#ifdef CONFIG_BOARD_ECC_SUPPORT #define ECC_SUPPORT +#endif #define NEW_FABRIC_TWSI_ADDR 0x4E #ifdef CONFIG_DB_784MP_GP #define BUS_WIDTH_ECC_TWSI_ADDR 0x4E diff --git a/drivers/ddr/marvell/axp/ddr3_axp_config.h b/drivers/ddr/marvell/axp/ddr3_axp_config.h index a672044..8549fe8 100644 --- a/drivers/ddr/marvell/axp/ddr3_axp_config.h +++ b/drivers/ddr/marvell/axp/ddr3_axp_config.h @@ -44,9 +44,14 @@ * DDR3_TRAINING_DEBUG - Debug prints of internal code */ #define DDR_TARGET_FABRIC 5 +/* Only enable ECC if the board selects it */ +#ifdef CONFIG_BOARD_ECC_SUPPORT #define DRAM_ECC 1 +#else +#define DRAM_ECC 0 +#endif -#ifdef MV_DDR_32BIT +#ifdef CONFIG_DDR_32BIT #define BUS_WIDTH 32 #else #define BUS_WIDTH 64 diff --git a/drivers/ddr/marvell/axp/ddr3_axp_mc_static.h b/drivers/ddr/marvell/axp/ddr3_axp_mc_static.h index 2c0e9075..71794ad 100644 --- a/drivers/ddr/marvell/axp/ddr3_axp_mc_static.h +++ b/drivers/ddr/marvell/axp/ddr3_axp_mc_static.h @@ -8,9 +8,9 @@ #define __AXP_MC_STATIC_H MV_DRAM_MC_INIT ddr3_A0_db_667[MV_MAX_DDR3_STATIC_SIZE] = { -#ifdef MV_DDR_32BIT +#ifdef CONFIG_DDR_32BIT {0x00001400, 0x7301c924}, /*DDR SDRAM Configuration Register */ -#else /*MV_DDR_64BIT */ +#else /*CONFIG_DDR_64BIT */ {0x00001400, 0x7301CA28}, /*DDR SDRAM Configuration Register */ #endif {0x00001404, 0x3630b800}, /*Dunit Control Low Register */ @@ -66,9 +66,9 @@ MV_DRAM_MC_INIT ddr3_A0_db_667[MV_MAX_DDR3_STATIC_SIZE] = { }; MV_DRAM_MC_INIT ddr3_A0_AMC_667[MV_MAX_DDR3_STATIC_SIZE] = { -#ifdef MV_DDR_32BIT +#ifdef CONFIG_DDR_32BIT {0x00001400, 0x7301c924}, /*DDR SDRAM Configuration Register */ -#else /*MV_DDR_64BIT */ +#else /*CONFIG_DDR_64BIT */ {0x00001400, 0x7301CA28}, /*DDR SDRAM Configuration Register */ #endif {0x00001404, 0x3630b800}, /*Dunit Control Low Register */ @@ -124,9 +124,9 @@ MV_DRAM_MC_INIT ddr3_A0_AMC_667[MV_MAX_DDR3_STATIC_SIZE] = { }; MV_DRAM_MC_INIT ddr3_A0_db_400[MV_MAX_DDR3_STATIC_SIZE] = { -#ifdef MV_DDR_32BIT +#ifdef CONFIG_DDR_32BIT {0x00001400, 0x73004C30}, /*DDR SDRAM Configuration Register */ -#else /* MV_DDR_64BIT */ +#else /* CONFIG_DDR_64BIT */ {0x00001400, 0x7300CC30}, /*DDR SDRAM Configuration Register */ #endif {0x00001404, 0x3630B840}, /*Dunit Control Low Register */ @@ -176,9 +176,9 @@ MV_DRAM_MC_INIT ddr3_A0_db_400[MV_MAX_DDR3_STATIC_SIZE] = { }; MV_DRAM_MC_INIT ddr3_Z1_db_600[MV_MAX_DDR3_STATIC_SIZE] = { -#ifdef MV_DDR_32BIT +#ifdef CONFIG_DDR_32BIT {0x00001400, 0x73014A28}, /*DDR SDRAM Configuration Register */ -#else /*MV_DDR_64BIT */ +#else /*CONFIG_DDR_64BIT */ {0x00001400, 0x7301CA28}, /*DDR SDRAM Configuration Register */ #endif {0x00001404, 0x3630B040}, /*Dunit Control Low Register */ @@ -233,9 +233,9 @@ MV_DRAM_MC_INIT ddr3_Z1_db_600[MV_MAX_DDR3_STATIC_SIZE] = { }; MV_DRAM_MC_INIT ddr3_Z1_db_300[MV_MAX_DDR3_STATIC_SIZE] = { -#ifdef MV_DDR_32BIT +#ifdef CONFIG_DDR_32BIT {0x00001400, 0x73004C30}, /*DDR SDRAM Configuration Register */ -#else /*MV_DDR_64BIT */ +#else /*CONFIG_DDR_64BIT */ {0x00001400, 0x7300CC30}, /*DDR SDRAM Configuration Register */ /*{0x00001400, 0x7304CC30}, *//*DDR SDRAM Configuration Register */ #endif diff --git a/drivers/ddr/marvell/axp/ddr3_write_leveling.c b/drivers/ddr/marvell/axp/ddr3_write_leveling.c index df3a3df..da384f3 100644 --- a/drivers/ddr/marvell/axp/ddr3_write_leveling.c +++ b/drivers/ddr/marvell/axp/ddr3_write_leveling.c @@ -22,6 +22,8 @@ DEBUG_WL_FULL_S(s); DEBUG_WL_FULL_D(d, l); DEBUG_WL_FULL_S("\n") #ifdef MV_DEBUG_WL +#define DEBUG_WL_S(s) puts(s) +#define DEBUG_WL_D(d, l) printf("%x", d) #define DEBUG_RL_S(s) \ debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s) #define DEBUG_RL_D(d, l) \ @@ -1229,8 +1231,6 @@ static int ddr3_write_leveling_single_cs(u32 cs, u32 freq, int ratio_2to1, DEBUG_WL_FULL_D((u32) phase, 1); DEBUG_WL_FULL_S(", Delay = "); DEBUG_WL_FULL_D((u32) delay, 1); - DEBUG_WL_FULL_S(", Counter = "); - DEBUG_WL_FULL_D((u32) i, 1); DEBUG_WL_FULL_S("\n"); /* Drive DQS high for one cycle - All data PUPs */ diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index f20d1b2..5dc4fbb 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -20,7 +20,7 @@ #if defined(CONFIG_ORION5X) #include <asm/arch/orion5x.h> -#elif (defined(CONFIG_KIRKWOOD) || defined(CONFIG_ARMADA_XP)) +#elif (defined(CONFIG_KIRKWOOD) || defined(CONFIG_ARCH_MVEBU)) #include <asm/arch/soc.h> #elif defined(CONFIG_SUNXI) #include <asm/arch/i2c.h> diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c index 38ad14e..fa20f54 100644 --- a/drivers/net/mvneta.c +++ b/drivers/net/mvneta.c @@ -2,7 +2,7 @@ * Driver for Marvell NETA network card for Armada XP and Armada 370 SoCs. * * U-Boot version: - * Copyright (C) 2014 Stefan Roese <sr@denx.de> + * Copyright (C) 2014-2015 Stefan Roese <sr@denx.de> * * Based on the Linux version which is: * Copyright (C) 2012 Marvell @@ -14,6 +14,7 @@ */ #include <common.h> +#include <dm.h> #include <net.h> #include <netdev.h> #include <config.h> @@ -28,6 +29,8 @@ #include <linux/compat.h> #include <linux/mbus.h> +DECLARE_GLOBAL_DATA_PTR; + #if !defined(CONFIG_PHYLIB) # error Marvell mvneta requires PHYLIB #endif @@ -1115,9 +1118,9 @@ static void mvneta_start_dev(struct mvneta_port *pp) mvneta_port_enable(pp); } -static void mvneta_adjust_link(struct eth_device *dev) +static void mvneta_adjust_link(struct udevice *dev) { - struct mvneta_port *pp = dev->priv; + struct mvneta_port *pp = dev_get_priv(dev); struct phy_device *phydev = pp->phydev; int status_change = 0; @@ -1171,9 +1174,9 @@ static void mvneta_adjust_link(struct eth_device *dev) } } -static int mvneta_open(struct eth_device *dev) +static int mvneta_open(struct udevice *dev) { - struct mvneta_port *pp = dev->priv; + struct mvneta_port *pp = dev_get_priv(dev); int ret; ret = mvneta_setup_rxqs(pp); @@ -1192,7 +1195,7 @@ static int mvneta_open(struct eth_device *dev) } /* Initialize hw */ -static int mvneta_init(struct mvneta_port *pp) +static int mvneta_init2(struct mvneta_port *pp) { int queue; @@ -1314,23 +1317,22 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) } /* Device initialization routine */ -static int mvneta_probe(struct eth_device *dev) +static int mvneta_init(struct udevice *dev) { - struct mvneta_port *pp = dev->priv; + struct eth_pdata *pdata = dev_get_platdata(dev); + struct mvneta_port *pp = dev_get_priv(dev); int err; pp->tx_ring_size = MVNETA_MAX_TXD; pp->rx_ring_size = MVNETA_MAX_RXD; - err = mvneta_init(pp); + err = mvneta_init2(pp); if (err < 0) { dev_err(&pdev->dev, "can't init eth hal\n"); return err; } - mvneta_conf_mbus_windows(pp); - - mvneta_mac_addr_set(pp, dev->enetaddr, rxq_def); + mvneta_mac_addr_set(pp, pdata->enetaddr, rxq_def); err = mvneta_port_power_up(pp, pp->phy_interface); if (err < 0) { @@ -1367,25 +1369,24 @@ static int smi_wait_ready(struct mvneta_port *pp) } /* - * smi_reg_read - miiphy_read callback function. + * mvneta_mdio_read - miiphy_read callback function. * * Returns 16bit phy register value, or 0xffff on error */ -static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data) +static int mvneta_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) { - struct eth_device *dev = eth_get_dev_by_name(devname); - struct mvneta_port *pp = dev->priv; + struct mvneta_port *pp = bus->priv; u32 smi_reg; u32 timeout; /* check parameters */ - if (phy_adr > MVNETA_PHY_ADDR_MASK) { - printf("Error: Invalid PHY address %d\n", phy_adr); + if (addr > MVNETA_PHY_ADDR_MASK) { + printf("Error: Invalid PHY address %d\n", addr); return -EFAULT; } - if (reg_ofs > MVNETA_PHY_REG_MASK) { - printf("Err: Invalid register offset %d\n", reg_ofs); + if (reg > MVNETA_PHY_REG_MASK) { + printf("Err: Invalid register offset %d\n", reg); return -EFAULT; } @@ -1394,14 +1395,14 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data) return -EFAULT; /* fill the phy address and regiser offset and read opcode */ - smi_reg = (phy_adr << MVNETA_SMI_DEV_ADDR_OFFS) - | (reg_ofs << MVNETA_SMI_REG_ADDR_OFFS) + smi_reg = (addr << MVNETA_SMI_DEV_ADDR_OFFS) + | (reg << MVNETA_SMI_REG_ADDR_OFFS) | MVNETA_SMI_OPCODE_READ; /* write the smi register */ mvreg_write(pp, MVNETA_SMI, smi_reg); - /*wait till read value is ready */ + /* wait till read value is ready */ timeout = MVNETA_SMI_TIMEOUT; do { @@ -1417,31 +1418,29 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data) for (timeout = 0; timeout < MVNETA_SMI_TIMEOUT; timeout++) ; - *data = (u16)(mvreg_read(pp, MVNETA_SMI) & MVNETA_SMI_DATA_MASK); - - return 0; + return mvreg_read(pp, MVNETA_SMI) & MVNETA_SMI_DATA_MASK; } /* - * smi_reg_write - imiiphy_write callback function. + * mvneta_mdio_write - miiphy_write callback function. * * Returns 0 if write succeed, -EINVAL on bad parameters * -ETIME on timeout */ -static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data) +static int mvneta_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, + u16 value) { - struct eth_device *dev = eth_get_dev_by_name(devname); - struct mvneta_port *pp = dev->priv; + struct mvneta_port *pp = bus->priv; u32 smi_reg; /* check parameters */ - if (phy_adr > MVNETA_PHY_ADDR_MASK) { - printf("Error: Invalid PHY address %d\n", phy_adr); + if (addr > MVNETA_PHY_ADDR_MASK) { + printf("Error: Invalid PHY address %d\n", addr); return -EFAULT; } - if (reg_ofs > MVNETA_PHY_REG_MASK) { - printf("Err: Invalid register offset %d\n", reg_ofs); + if (reg > MVNETA_PHY_REG_MASK) { + printf("Err: Invalid register offset %d\n", reg); return -EFAULT; } @@ -1450,9 +1449,9 @@ static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data) return -EFAULT; /* fill the phy addr and reg offset and write opcode and data */ - smi_reg = (data << MVNETA_SMI_DATA_OFFS); - smi_reg |= (phy_adr << MVNETA_SMI_DEV_ADDR_OFFS) - | (reg_ofs << MVNETA_SMI_REG_ADDR_OFFS); + smi_reg = value << MVNETA_SMI_DATA_OFFS; + smi_reg |= (addr << MVNETA_SMI_DEV_ADDR_OFFS) + | (reg << MVNETA_SMI_REG_ADDR_OFFS); smi_reg &= ~MVNETA_SMI_OPCODE_READ; /* write the smi register */ @@ -1461,9 +1460,9 @@ static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data) return 0; } -static int mvneta_init_u_boot(struct eth_device *dev, bd_t *bis) +static int mvneta_start(struct udevice *dev) { - struct mvneta_port *pp = dev->priv; + struct mvneta_port *pp = dev_get_priv(dev); struct phy_device *phydev; mvneta_port_power_up(pp, pp->phy_interface); @@ -1483,7 +1482,7 @@ static int mvneta_init_u_boot(struct eth_device *dev, bd_t *bis) } /* Full init on first call */ - mvneta_probe(dev); + mvneta_init(dev); pp->init = 1; } else { /* Upon all following calls, this is enough */ @@ -1494,9 +1493,9 @@ static int mvneta_init_u_boot(struct eth_device *dev, bd_t *bis) return 0; } -static int mvneta_send(struct eth_device *dev, void *ptr, int len) +static int mvneta_send(struct udevice *dev, void *packet, int length) { - struct mvneta_port *pp = dev->priv; + struct mvneta_port *pp = dev_get_priv(dev); struct mvneta_tx_queue *txq = &pp->txqs[0]; struct mvneta_tx_desc *tx_desc; int sent_desc; @@ -1505,9 +1504,9 @@ static int mvneta_send(struct eth_device *dev, void *ptr, int len) /* Get a descriptor for the first part of the packet */ tx_desc = mvneta_txq_next_desc_get(txq); - tx_desc->buf_phys_addr = (u32)ptr; - tx_desc->data_size = len; - flush_dcache_range((u32)ptr, (u32)ptr + len); + tx_desc->buf_phys_addr = (u32)packet; + tx_desc->data_size = length; + flush_dcache_range((u32)packet, (u32)packet + length); /* First and Last descriptor */ tx_desc->command = MVNETA_TX_L4_CSUM_NOT | MVNETA_TXD_FLZ_DESC; @@ -1525,28 +1524,25 @@ static int mvneta_send(struct eth_device *dev, void *ptr, int len) /* txDone has increased - hw sent packet */ mvneta_txq_sent_desc_dec(pp, txq, sent_desc); - return 0; return 0; } -static int mvneta_recv(struct eth_device *dev) +static int mvneta_recv(struct udevice *dev, int flags, uchar **packetp) { - struct mvneta_port *pp = dev->priv; + struct mvneta_port *pp = dev_get_priv(dev); int rx_done; - int packets_done; struct mvneta_rx_queue *rxq; + int rx_bytes = 0; /* get rx queue */ rxq = mvneta_rxq_handle_get(pp, rxq_def); rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq); - packets_done = rx_done; - while (packets_done--) { + if (rx_done) { struct mvneta_rx_desc *rx_desc; unsigned char *data; u32 rx_status; - int rx_bytes; /* * No cache invalidation needed here, since the desc's are @@ -1559,7 +1555,7 @@ static int mvneta_recv(struct eth_device *dev) (rx_status & MVNETA_RXD_ERR_SUMMARY)) { mvneta_rx_error(pp, rx_desc); /* leave the descriptor untouched */ - continue; + return -EIO; } /* 2 bytes for marvell header. 4 bytes for crc */ @@ -1571,40 +1567,24 @@ static int mvneta_recv(struct eth_device *dev) * No cache invalidation needed here, since the rx_buffer's are * located in a uncached memory region */ - net_process_received_packet(data, rx_bytes); - } + *packetp = data; - /* Update rxq management counters */ - if (rx_done) mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done); + } - return 0; -} - -static void mvneta_halt(struct eth_device *dev) -{ - struct mvneta_port *pp = dev->priv; - - mvneta_port_down(pp); - mvneta_port_disable(pp); + return rx_bytes; } -int mvneta_initialize(bd_t *bis, int base_addr, int devnum, int phy_addr) +static int mvneta_probe(struct udevice *dev) { - struct eth_device *dev; - struct mvneta_port *pp; + struct eth_pdata *pdata = dev_get_platdata(dev); + struct mvneta_port *pp = dev_get_priv(dev); + void *blob = (void *)gd->fdt_blob; + int node = dev->of_offset; + struct mii_dev *bus; + unsigned long addr; void *bd_space; - dev = calloc(1, sizeof(*dev)); - if (dev == NULL) - return -ENOMEM; - - pp = calloc(1, sizeof(*pp)); - if (pp == NULL) - return -ENOMEM; - - dev->priv = pp; - /* * Allocate buffer area for descs and rx_buffers. This is only * done once for all interfaces. As only one interface can @@ -1625,28 +1605,82 @@ int mvneta_initialize(bd_t *bis, int base_addr, int devnum, int phy_addr) MVNETA_MAX_RXD * sizeof(struct mvneta_rx_desc)); } - sprintf(dev->name, "neta%d", devnum); + pp->base = (void __iomem *)pdata->iobase; - pp->base = (void __iomem *)base_addr; - dev->iobase = base_addr; - dev->init = mvneta_init_u_boot; - dev->halt = mvneta_halt; - dev->send = mvneta_send; - dev->recv = mvneta_recv; - dev->write_hwaddr = NULL; + /* Configure MBUS address windows */ + mvneta_conf_mbus_windows(pp); - /* - * The PHY interface type is configured via the - * board specific CONFIG_SYS_NETA_INTERFACE_TYPE - * define. - */ - pp->phy_interface = CONFIG_SYS_NETA_INTERFACE_TYPE; + /* PHY interface is already decoded in mvneta_ofdata_to_platdata() */ + pp->phy_interface = pdata->phy_interface; + + /* Now read phyaddr from DT */ + addr = fdtdec_get_int(blob, node, "phy", 0); + addr = fdt_node_offset_by_phandle(blob, addr); + pp->phyaddr = fdtdec_get_int(blob, addr, "reg", 0); + + bus = mdio_alloc(); + if (!bus) { + printf("Failed to allocate MDIO bus\n"); + return -ENOMEM; + } + + bus->read = mvneta_mdio_read; + bus->write = mvneta_mdio_write; + snprintf(bus->name, sizeof(bus->name), dev->name); + bus->priv = (void *)pp; + pp->bus = bus; - eth_register(dev); + return mdio_register(bus); +} - pp->phyaddr = phy_addr; - miiphy_register(dev->name, smi_reg_read, smi_reg_write); - pp->bus = miiphy_get_dev_by_name(dev->name); +static void mvneta_stop(struct udevice *dev) +{ + struct mvneta_port *pp = dev_get_priv(dev); - return 1; + mvneta_port_down(pp); + mvneta_port_disable(pp); } + +static const struct eth_ops mvneta_ops = { + .start = mvneta_start, + .send = mvneta_send, + .recv = mvneta_recv, + .stop = mvneta_stop, +}; + +static int mvneta_ofdata_to_platdata(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + const char *phy_mode; + + pdata->iobase = dev_get_addr(dev); + + /* Get phy-mode / phy_interface from DT */ + pdata->phy_interface = -1; + phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL); + if (phy_mode) + pdata->phy_interface = phy_get_interface_by_name(phy_mode); + if (pdata->phy_interface == -1) { + debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); + return -EINVAL; + } + + return 0; +} + +static const struct udevice_id mvneta_ids[] = { + { .compatible = "marvell,armada-370-neta" }, + { .compatible = "marvell,armada-xp-neta" }, + { } +}; + +U_BOOT_DRIVER(mvneta) = { + .name = "mvneta", + .id = UCLASS_ETH, + .of_match = mvneta_ids, + .ofdata_to_platdata = mvneta_ofdata_to_platdata, + .probe = mvneta_probe, + .ops = &mvneta_ops, + .priv_auto_alloc_size = sizeof(struct mvneta_port), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; diff --git a/drivers/pci/pci_auto_old.c b/drivers/pci/pci_auto_old.c index 9126f78..edc9a7b 100644 --- a/drivers/pci/pci_auto_old.c +++ b/drivers/pci/pci_auto_old.c @@ -101,11 +101,11 @@ void pciauto_setup_device(struct pci_controller *hose, bar_res = prefetch; else bar_res = mem; -#endif debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ", bar_nr, bar_res == prefetch ? "Prf" : "Mem", (unsigned long long)bar_size); +#endif } #ifndef CONFIG_PCI_ENUM_ONLY diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c index fd2744d..4eedfe1 100644 --- a/drivers/pci/pci_mvebu.c +++ b/drivers/pci/pci_mvebu.c @@ -155,6 +155,14 @@ static void mvebu_get_port_lane(struct mvebu_pcie *pcie, int pex_idx, } #endif +static int mvebu_pex_unit_is_x4(int pex_idx) +{ + int pex_unit = pex_idx < 9 ? pex_idx >> 2 : 3; + u32 mask = (0x0f << (pex_unit * 8)); + + return (readl(COMPHY_REFCLK_ALIGNMENT) & mask) == mask; +} + static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie) { u32 val; @@ -419,5 +427,11 @@ void pci_init_board(void) writel(0, pcie->base + PCIE_BAR_HI_OFF(0)); bus = hose->last_busno + 1; + + /* need to skip more for X4 links, otherwise scan will hang */ + if (mvebu_soc_family() == MVEBU_SOC_AXP) { + if (mvebu_pex_unit_is_x4(i)) + i += 3; + } } } diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c index e7b0982..7890796 100644 --- a/drivers/spi/kirkwood_spi.c +++ b/drivers/spi/kirkwood_spi.c @@ -9,6 +9,7 @@ */ #include <common.h> +#include <dm.h> #include <malloc.h> #include <spi.h> #include <asm/io.h> @@ -18,6 +19,83 @@ #endif #include <asm/arch-mvebu/spi.h> +static void _spi_cs_activate(struct kwspi_registers *reg) +{ + setbits_le32(®->ctrl, KWSPI_CSN_ACT); +} + +static void _spi_cs_deactivate(struct kwspi_registers *reg) +{ + clrbits_le32(®->ctrl, KWSPI_CSN_ACT); +} + +static int _spi_xfer(struct kwspi_registers *reg, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + unsigned int tmpdout, tmpdin; + int tm, isread = 0; + + debug("spi_xfer: dout %p din %p bitlen %u\n", dout, din, bitlen); + + if (flags & SPI_XFER_BEGIN) + _spi_cs_activate(reg); + + /* + * handle data in 8-bit chunks + * TBD: 2byte xfer mode to be enabled + */ + clrsetbits_le32(®->cfg, KWSPI_XFERLEN_MASK, KWSPI_XFERLEN_1BYTE); + + while (bitlen > 4) { + debug("loopstart bitlen %d\n", bitlen); + tmpdout = 0; + + /* Shift data so it's msb-justified */ + if (dout) + tmpdout = *(u32 *)dout & 0xff; + + clrbits_le32(®->irq_cause, KWSPI_SMEMRDIRQ); + writel(tmpdout, ®->dout); /* Write the data out */ + debug("*** spi_xfer: ... %08x written, bitlen %d\n", + tmpdout, bitlen); + + /* + * Wait for SPI transmit to get out + * or time out (1 second = 1000 ms) + * The NE event must be read and cleared first + */ + for (tm = 0, isread = 0; tm < KWSPI_TIMEOUT; ++tm) { + if (readl(®->irq_cause) & KWSPI_SMEMRDIRQ) { + isread = 1; + tmpdin = readl(®->din); + debug("spi_xfer: din %p..%08x read\n", + din, tmpdin); + + if (din) { + *((u8 *)din) = (u8)tmpdin; + din += 1; + } + if (dout) + dout += 1; + bitlen -= 8; + } + if (isread) + break; + } + if (tm >= KWSPI_TIMEOUT) + printf("*** spi_xfer: Time out during SPI transfer\n"); + + debug("loopend bitlen %d\n", bitlen); + } + + if (flags & SPI_XFER_END) + _spi_cs_deactivate(reg); + + return 0; +} + +#ifndef CONFIG_DM_SPI + static struct kwspi_registers *spireg = (struct kwspi_registers *)MVEBU_SPI_BASE; @@ -147,76 +225,109 @@ void spi_init(void) void spi_cs_activate(struct spi_slave *slave) { - setbits_le32(&spireg->ctrl, KWSPI_CSN_ACT); + _spi_cs_activate(spireg); } void spi_cs_deactivate(struct spi_slave *slave) { - clrbits_le32(&spireg->ctrl, KWSPI_CSN_ACT); + _spi_cs_deactivate(spireg); } -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, - void *din, unsigned long flags) +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) { - unsigned int tmpdout, tmpdin; - int tm, isread = 0; + return _spi_xfer(spireg, bitlen, dout, din, flags); +} - debug("spi_xfer: slave %u:%u dout %p din %p bitlen %u\n", - slave->bus, slave->cs, dout, din, bitlen); +#else - if (flags & SPI_XFER_BEGIN) - spi_cs_activate(slave); +/* Here now the DM part */ - /* - * handle data in 8-bit chunks - * TBD: 2byte xfer mode to be enabled - */ - clrsetbits_le32(&spireg->cfg, KWSPI_XFERLEN_MASK, KWSPI_XFERLEN_1BYTE); +struct mvebu_spi_platdata { + struct kwspi_registers *spireg; +}; - while (bitlen > 4) { - debug("loopstart bitlen %d\n", bitlen); - tmpdout = 0; +struct mvebu_spi_priv { + struct kwspi_registers *spireg; +}; - /* Shift data so it's msb-justified */ - if (dout) - tmpdout = *(u32 *)dout & 0xff; +static int mvebu_spi_set_speed(struct udevice *bus, uint hz) +{ + struct mvebu_spi_platdata *plat = dev_get_platdata(bus); + struct kwspi_registers *reg = plat->spireg; + u32 data; - clrbits_le32(&spireg->irq_cause, KWSPI_SMEMRDIRQ); - writel(tmpdout, &spireg->dout); /* Write the data out */ - debug("*** spi_xfer: ... %08x written, bitlen %d\n", - tmpdout, bitlen); + /* calculate spi clock prescaller using max_hz */ + data = ((CONFIG_SYS_TCLK / 2) / hz) + 0x10; + data = data < KWSPI_CLKPRESCL_MIN ? KWSPI_CLKPRESCL_MIN : data; + data = data > KWSPI_CLKPRESCL_MASK ? KWSPI_CLKPRESCL_MASK : data; - /* - * Wait for SPI transmit to get out - * or time out (1 second = 1000 ms) - * The NE event must be read and cleared first - */ - for (tm = 0, isread = 0; tm < KWSPI_TIMEOUT; ++tm) { - if (readl(&spireg->irq_cause) & KWSPI_SMEMRDIRQ) { - isread = 1; - tmpdin = readl(&spireg->din); - debug("spi_xfer: din %p..%08x read\n", - din, tmpdin); + /* program spi clock prescaler using max_hz */ + writel(KWSPI_ADRLEN_3BYTE | data, ®->cfg); + debug("data = 0x%08x\n", data); - if (din) { - *((u8 *)din) = (u8)tmpdin; - din += 1; - } - if (dout) - dout += 1; - bitlen -= 8; - } - if (isread) - break; - } - if (tm >= KWSPI_TIMEOUT) - printf("*** spi_xfer: Time out during SPI transfer\n"); + return 0; +} - debug("loopend bitlen %d\n", bitlen); - } +static int mvebu_spi_set_mode(struct udevice *bus, uint mode) +{ + return 0; +} - if (flags & SPI_XFER_END) - spi_cs_deactivate(slave); +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); + + return _spi_xfer(plat->spireg, bitlen, dout, din, flags); +} + +static int mvebu_spi_probe(struct udevice *bus) +{ + struct mvebu_spi_platdata *plat = dev_get_platdata(bus); + struct kwspi_registers *reg = plat->spireg; + + writel(KWSPI_SMEMRDY, ®->ctrl); + writel(KWSPI_SMEMRDIRQ, ®->irq_cause); + writel(KWSPI_IRQMASK, ®->irq_mask); + + return 0; +} + +static int mvebu_spi_ofdata_to_platdata(struct udevice *bus) +{ + struct mvebu_spi_platdata *plat = dev_get_platdata(bus); + + plat->spireg = (struct kwspi_registers *)dev_get_addr(bus); 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-380-spi" }, + { .compatible = "marvell,armada-xp-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), + .priv_auto_alloc_size = sizeof(struct mvebu_spi_priv), + .probe = mvebu_spi_probe, +}; +#endif diff --git a/include/configs/clearfog.h b/include/configs/clearfog.h new file mode 100644 index 0000000..f0de827 --- /dev/null +++ b/include/configs/clearfog.h @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2015 Stefan Roese <sr@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _CONFIG_CLEARFOG_H +#define _CONFIG_CLEARFOG_H + +/* + * High Level Configuration Options (easy to change) + */ + +#define CONFIG_DISPLAY_BOARDINFO_LATE + +/* + * TEXT_BASE needs to be below 16MiB, since this area is scrubbed + * for DDR ECC byte filling in the SPL before loading the main + * U-Boot into it. + */ +#define CONFIG_SYS_TEXT_BASE 0x00800000 +#define CONFIG_SYS_TCLK 250000000 /* 250MHz */ + +/* + * Commands configuration + */ +#define CONFIG_SYS_NO_FLASH /* Declare no flash (NOR/SPI) */ +#define CONFIG_CMD_BOOTZ +#define CONFIG_CMD_CACHE +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_ENV +#define CONFIG_CMD_EXT2 +#define CONFIG_CMD_EXT4 +#define CONFIG_CMD_FAT +#define CONFIG_CMD_FS_GENERIC +#define CONFIG_CMD_I2C +#define CONFIG_CMD_MMC +#define CONFIG_CMD_PCI +#define CONFIG_CMD_PING +#define CONFIG_CMD_SF +#define CONFIG_CMD_SPI +#define CONFIG_CMD_TFTPPUT +#define CONFIG_CMD_TIME + +/* I2C */ +#define CONFIG_SYS_I2C +#define CONFIG_SYS_I2C_MVTWSI +#define CONFIG_I2C_MVTWSI_BASE0 MVEBU_TWSI_BASE +#define CONFIG_SYS_I2C_SLAVE 0x0 +#define CONFIG_SYS_I2C_SPEED 100000 + +/* SPI NOR flash default params, used by sf commands */ +#define CONFIG_SF_DEFAULT_SPEED 1000000 +#define CONFIG_SF_DEFAULT_MODE SPI_MODE_3 +#define CONFIG_SPI_FLASH_STMICRO + +/* + * SDIO/MMC Card Configuration + */ +#define CONFIG_MMC +#define CONFIG_MMC_SDMA +#define CONFIG_GENERIC_MMC +#define CONFIG_SDHCI +#define CONFIG_MV_SDHCI +#define CONFIG_SYS_MMC_BASE MVEBU_SDIO_BASE + +/* Partition support */ +#define CONFIG_DOS_PARTITION +#define CONFIG_EFI_PARTITION + +/* Additional FS support/configuration */ +#define CONFIG_SUPPORT_VFAT + +/* USB/EHCI configuration */ +#define CONFIG_EHCI_IS_TDI + +#define CONFIG_ENV_MIN_ENTRIES 128 + +/* Environment in MMC */ +#define CONFIG_ENV_IS_IN_MMC +#define CONFIG_SYS_MMC_ENV_DEV 0 +#define CONFIG_ENV_SECT_SIZE 0x200 +#define CONFIG_ENV_SIZE 0x10000 +/* + * For SD - reserve 1 LBA for MBR + 1M for u-boot image. The MMC/eMMC + * boot image starts @ LBA-0. + * As result in MMC/eMMC case it will be a 1 sector gap between u-boot + * image and environment + */ +#define CONFIG_ENV_OFFSET 0xf0000 +#define CONFIG_ENV_ADDR CONFIG_ENV_OFFSET + +#define CONFIG_PHY_MARVELL /* there is a marvell phy */ +#define PHY_ANEG_TIMEOUT 8000 /* PHY needs a longer aneg time */ + +/* PCIe support */ +#ifndef CONFIG_SPL_BUILD +#define CONFIG_PCI +#define CONFIG_PCI_MVEBU +#define CONFIG_PCI_PNP +#define CONFIG_PCI_SCAN_SHOW +#endif + +#define CONFIG_SYS_CONSOLE_INFO_QUIET /* don't print console @ startup */ +#define CONFIG_SYS_ALT_MEMTEST + +/* Keep device tree and initrd in lower memory so the kernel can access them */ +#define CONFIG_EXTRA_ENV_SETTINGS \ + "fdt_high=0x10000000\0" \ + "initrd_high=0x10000000\0" + +/* SPL */ +/* + * Select the boot device here + * + * Currently supported are: + * SPL_BOOT_SPI_NOR_FLASH - Booting via SPI NOR flash + * SPL_BOOT_SDIO_MMC_CARD - Booting via SDIO/MMC card (partition 1) + */ +#define SPL_BOOT_SPI_NOR_FLASH 1 +#define SPL_BOOT_SDIO_MMC_CARD 2 +#define CONFIG_SPL_BOOT_DEVICE SPL_BOOT_SDIO_MMC_CARD + +/* Defines for SPL */ +#define CONFIG_SPL_FRAMEWORK +#define CONFIG_SPL_SIZE (140 << 10) +#define CONFIG_SPL_TEXT_BASE 0x40000030 +#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - 0x0030) + +#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + CONFIG_SPL_SIZE) +#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10) + +#ifdef CONFIG_SPL_BUILD +#define CONFIG_SYS_MALLOC_SIMPLE +#endif + +#define CONFIG_SPL_STACK (0x40000000 + ((192 - 16) << 10)) +#define CONFIG_SPL_BOOTROM_SAVE (CONFIG_SPL_STACK + 4) + +#define CONFIG_SPL_LIBCOMMON_SUPPORT +#define CONFIG_SPL_LIBGENERIC_SUPPORT +#define CONFIG_SPL_SERIAL_SUPPORT +#define CONFIG_SPL_I2C_SUPPORT + +#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SPI_NOR_FLASH +/* SPL related SPI defines */ +#define CONFIG_SPL_SPI_SUPPORT +#define CONFIG_SPL_SPI_FLASH_SUPPORT +#define CONFIG_SPL_SPI_LOAD +#define CONFIG_SPL_SPI_BUS 0 +#define CONFIG_SPL_SPI_CS 0 +#define CONFIG_SYS_SPI_U_BOOT_OFFS 0x20000 +#define CONFIG_SYS_U_BOOT_OFFS CONFIG_SYS_SPI_U_BOOT_OFFS +#endif + +#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SDIO_MMC_CARD +/* SPL related MMC defines */ +#define CONFIG_SPL_MMC_SUPPORT +#define CONFIG_SPL_LIBDISK_SUPPORT +#define CONFIG_SYS_MMC_U_BOOT_OFFS (160 << 10) +#define CONFIG_SYS_U_BOOT_OFFS CONFIG_SYS_MMC_U_BOOT_OFFS +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR ((CONFIG_SYS_U_BOOT_OFFS / 512)\ + + 1) +#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS ((512 << 10) / 512) /* 512KiB */ +#ifdef CONFIG_SPL_BUILD +#define CONFIG_FIXED_SDHCI_ALIGNED_BUFFER 0x00180000 /* in SDRAM */ +#endif +#endif + +/* + * mv-common.h should be defined after CMD configs since it used them + * to enable certain macros + */ +#include "mv-common.h" + +#endif /* _CONFIG_CLEARFOG_H */ diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h index 3673e5e..ef14132 100644 --- a/include/configs/db-88f6820-gp.h +++ b/include/configs/db-88f6820-gp.h @@ -10,15 +10,7 @@ /* * High Level Configuration Options (easy to change) */ -#define CONFIG_ARMADA_XP /* SOC Family Name */ -#define CONFIG_ARMADA_38X -#define CONFIG_DB_88F6820_GP /* Board target name for DDR training */ -#define CONFIG_SYS_L2_PL310 - -#ifdef CONFIG_SPL_BUILD -#define CONFIG_SKIP_LOWLEVEL_INIT /* disable board lowlevel_init */ -#endif #define CONFIG_DISPLAY_BOARDINFO_LATE /* @@ -99,16 +91,15 @@ #define CONFIG_ENV_SECT_SIZE (256 << 10) /* 256KiB sectors */ #define CONFIG_PHY_MARVELL /* there is a marvell phy */ -#define CONFIG_PHY_ADDR { 1, 0 } -#define CONFIG_SYS_NETA_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII #define PHY_ANEG_TIMEOUT 8000 /* PHY needs a longer aneg time */ /* PCIe support */ +#ifndef CONFIG_SPL_BUILD #define CONFIG_PCI #define CONFIG_PCI_MVEBU #define CONFIG_PCI_PNP #define CONFIG_PCI_SCAN_SHOW -#define CONFIG_E1000 /* enable Intel E1000 support for testing */ +#endif #define CONFIG_SYS_CONSOLE_INFO_QUIET /* don't print console @ startup */ #define CONFIG_SYS_ALT_MEMTEST @@ -139,9 +130,9 @@ #define CONFIG_SPL_BSS_START_ADDR (0x40000000 + CONFIG_SPL_SIZE) #define CONFIG_SPL_BSS_MAX_SIZE (16 << 10) -#define CONFIG_SYS_SPL_MALLOC_START (CONFIG_SPL_BSS_START_ADDR + \ - CONFIG_SPL_BSS_MAX_SIZE) -#define CONFIG_SYS_SPL_MALLOC_SIZE (16 << 10) +#ifdef CONFIG_SPL_BUILD +#define CONFIG_SYS_MALLOC_SIMPLE +#endif #define CONFIG_SPL_STACK (0x40000000 + ((192 - 16) << 10)) #define CONFIG_SPL_BOOTROM_SAVE (CONFIG_SPL_STACK + 4) @@ -158,7 +149,7 @@ #define CONFIG_SPL_SPI_LOAD #define CONFIG_SPL_SPI_BUS 0 #define CONFIG_SPL_SPI_CS 0 -#define CONFIG_SYS_SPI_U_BOOT_OFFS 0x20000 +#define CONFIG_SYS_SPI_U_BOOT_OFFS 0x24000 #define CONFIG_SYS_U_BOOT_OFFS CONFIG_SYS_SPI_U_BOOT_OFFS #endif @@ -176,10 +167,6 @@ #endif #endif -/* Enable DDR support in SPL (DDR3 training from Marvell bin_hdr) */ -#define CONFIG_SYS_MVEBU_DDR_A38X -#define CONFIG_DDR3 - /* * mv-common.h should be defined after CMD configs since it used them * to enable certain macros diff --git a/include/configs/db-mv784mp-gp.h b/include/configs/db-mv784mp-gp.h index ab6e5a5..c8b0344 100644 --- a/include/configs/db-mv784mp-gp.h +++ b/include/configs/db-mv784mp-gp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Stefan Roese <sr@denx.de> + * Copyright (C) 2014-2015 Stefan Roese <sr@denx.de> * * SPDX-License-Identifier: GPL-2.0+ */ @@ -10,12 +10,8 @@ /* * High Level Configuration Options (easy to change) */ -#define CONFIG_ARMADA_XP /* SOC Family Name */ #define CONFIG_DB_784MP_GP /* Board target name for DDR training */ -#ifdef CONFIG_SPL_BUILD -#define CONFIG_SKIP_LOWLEVEL_INIT /* disable board lowlevel_init */ -#endif #define CONFIG_DISPLAY_BOARDINFO_LATE /* @@ -30,13 +26,18 @@ * Commands configuration */ #define CONFIG_SYS_NO_FLASH /* Declare no flash (NOR/SPI) */ +#define CONFIG_CMD_CACHE #define CONFIG_CMD_DHCP #define CONFIG_CMD_ENV +#define CONFIG_CMD_EXT2 +#define CONFIG_CMD_EXT4 +#define CONFIG_CMD_FAT +#define CONFIG_CMD_FS_GENERIC #define CONFIG_CMD_I2C -#define CONFIG_CMD_IDE #define CONFIG_CMD_NAND #define CONFIG_CMD_PCI #define CONFIG_CMD_PING +#define CONFIG_CMD_SATA #define CONFIG_CMD_SF #define CONFIG_CMD_SPI #define CONFIG_CMD_TFTPPUT @@ -64,48 +65,29 @@ #define CONFIG_ENV_SECT_SIZE (64 << 10) /* 64KiB sectors */ #define CONFIG_PHY_MARVELL /* there is a marvell phy */ -#define CONFIG_PHY_ADDR { 0x10, 0x11, 0x12, 0x13 } -#define CONFIG_SYS_NETA_INTERFACE_TYPE PHY_INTERFACE_MODE_QSGMII #define PHY_ANEG_TIMEOUT 8000 /* PHY needs a longer aneg time */ -#define CONFIG_RESET_PHY_R #define CONFIG_SYS_CONSOLE_INFO_QUIET /* don't print console @ startup */ #define CONFIG_SYS_ALT_MEMTEST /* SATA support */ -#ifdef CONFIG_CMD_IDE -#define __io -#define CONFIG_IDE_PREINIT -#define CONFIG_MVSATA_IDE - -/* Needs byte-swapping for ATA data register */ -#define CONFIG_IDE_SWAP_IO - -#define CONFIG_SYS_ATA_REG_OFFSET 0x0100 /* Offset for register access */ -#define CONFIG_SYS_ATA_DATA_OFFSET 0x0100 /* Offset for data I/O */ -#define CONFIG_SYS_ATA_ALT_OFFSET 0x0100 - -/* Each 8-bit ATA register is aligned to a 4-bytes address */ -#define CONFIG_SYS_ATA_STRIDE 4 - -/* CONFIG_CMD_IDE requires some #defines for ATA registers */ -#define CONFIG_SYS_IDE_MAXBUS 2 -#define CONFIG_SYS_IDE_MAXDEVICE CONFIG_SYS_IDE_MAXBUS - -/* ATA registers base is at SATA controller base */ -#define CONFIG_SYS_ATA_BASE_ADDR MVEBU_AXP_SATA_BASE -#define CONFIG_SYS_ATA_IDE0_OFFSET 0x2000 -#define CONFIG_SYS_ATA_IDE1_OFFSET 0x4000 - +#define CONFIG_SYS_SATA_MAX_DEVICE 2 +#define CONFIG_SATA_MV +#define CONFIG_LIBATA +#define CONFIG_LBA48 +#define CONFIG_EFI_PARTITION #define CONFIG_DOS_PARTITION -#endif /* CONFIG_CMD_IDE */ + +/* Additional FS support/configuration */ +#define CONFIG_SUPPORT_VFAT /* PCIe support */ +#ifndef CONFIG_SPL_BUILD #define CONFIG_PCI #define CONFIG_PCI_MVEBU #define CONFIG_PCI_PNP #define CONFIG_PCI_SCAN_SHOW -#define CONFIG_E1000 /* enable Intel E1000 support for testing */ +#endif /* NAND */ #define CONFIG_SYS_NAND_USE_FLASH_BBT @@ -139,9 +121,9 @@ #define CONFIG_SPL_BSS_START_ADDR (0x40000000 + (128 << 10)) #define CONFIG_SPL_BSS_MAX_SIZE (16 << 10) -#define CONFIG_SYS_SPL_MALLOC_START (CONFIG_SPL_BSS_START_ADDR + \ - CONFIG_SPL_BSS_MAX_SIZE) -#define CONFIG_SYS_SPL_MALLOC_SIZE (16 << 10) +#ifdef CONFIG_SPL_BUILD +#define CONFIG_SYS_MALLOC_SIMPLE +#endif #define CONFIG_SPL_STACK (0x40000000 + ((192 - 16) << 10)) #define CONFIG_SPL_BOOTROM_SAVE (CONFIG_SPL_STACK + 4) @@ -161,7 +143,7 @@ #define CONFIG_SYS_U_BOOT_OFFS CONFIG_SYS_SPI_U_BOOT_OFFS /* Enable DDR support in SPL (DDR3 training from Marvell bin_hdr) */ -#define CONFIG_SYS_MVEBU_DDR_AXP #define CONFIG_SPD_EEPROM 0x4e +#define CONFIG_BOARD_ECC_SUPPORT /* this board supports ECC */ #endif /* _CONFIG_DB_MV7846MP_GP_H */ diff --git a/include/configs/ds414.h b/include/configs/ds414.h new file mode 100644 index 0000000..e3c7087 --- /dev/null +++ b/include/configs/ds414.h @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2014 Stefan Roese <sr@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _CONFIG_SYNOLOGY_DS414_H +#define _CONFIG_SYNOLOGY_DS414_H + +/* + * High Level Configuration Options (easy to change) + */ +#define CONFIG_DISPLAY_BOARDINFO_LATE + +/* + * TEXT_BASE needs to be below 16MiB, since this area is scrubbed + * for DDR ECC byte filling in the SPL before loading the main + * U-Boot into it. + */ +#define CONFIG_SYS_TEXT_BASE 0x00800000 +#define CONFIG_SYS_TCLK 250000000 /* 250MHz */ + +/* + * Commands configuration + */ +#define CONFIG_SYS_NO_FLASH /* Declare no flash (NOR/SPI) */ +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_ENV +#define CONFIG_CMD_I2C +#define CONFIG_CMD_PING +#define CONFIG_CMD_SF +#define CONFIG_CMD_SPI +#define CONFIG_CMD_TFTPPUT +#define CONFIG_CMD_TIME +#define CONFIG_CMD_USB + +/* I2C */ +#define CONFIG_SYS_I2C +#define CONFIG_SYS_I2C_MVTWSI +#define CONFIG_I2C_MVTWSI_BASE0 MVEBU_TWSI_BASE +#define CONFIG_SYS_I2C_SLAVE 0x0 +#define CONFIG_SYS_I2C_SPEED 100000 + +/* SPI NOR flash default params, used by sf commands */ +#define CONFIG_SF_DEFAULT_SPEED 1000000 +#define CONFIG_SF_DEFAULT_MODE SPI_MODE_3 + +/* Environment in SPI NOR flash */ +#define CONFIG_ENV_IS_IN_SPI_FLASH +#define CONFIG_ENV_OFFSET 0x7E0000 /* RedBoot config partition in DTS */ +#define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */ +#define CONFIG_ENV_SECT_SIZE (64 << 10) /* 64KiB sectors */ + +#define CONFIG_PHY_MARVELL /* there is a marvell phy */ +#define CONFIG_PHY_ADDR { 0x1, 0x0 } +#define CONFIG_SYS_NETA_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII + +#define CONFIG_SYS_ALT_MEMTEST + +/* PCIe support */ +#ifndef CONFIG_SPL_BUILD +#define CONFIG_PCI +#define CONFIG_CMD_PCI +#define CONFIG_CMD_PCI_ENUM +#define CONFIG_PCI_MVEBU +#define CONFIG_PCI_SCAN_SHOW +#endif + +/* USB/EHCI/XHCI configuration */ + +#define CONFIG_DM_USB +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 + +/* FIXME: broken XHCI support + * Below defines should enable support for the two rear USB3 ports. Sadly, this + * does not work because: + * - xhci-pci seems to not support DM_USB, so with that enabled it is not + * found. + * - USB init fails, controller does not respond in time */ +#if 0 +#undef CONFIG_DM_USB +#define CONFIG_USB_XHCI +#define CONFIG_USB_XHCI_PCI +#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 +#endif + +#if !defined(CONFIG_USB_XHCI) +#define CONFIG_USB_EHCI +#define CONFIG_USB_EHCI_MARVELL +#define CONFIG_EHCI_IS_TDI +#endif + +/* why is this only defined in mv-common.h if CONFIG_DM is undefined? */ +#define CONFIG_USB_STORAGE +#define CONFIG_DOS_PARTITION +#define CONFIG_ISO_PARTITION +#define CONFIG_SUPPORT_VFAT +#define CONFIG_SYS_MVFS + +/* + * mv-common.h should be defined after CMD configs since it used them + * to enable certain macros + */ +#include "mv-common.h" + +/* + * Memory layout while starting into the bin_hdr via the + * BootROM: + * + * 0x4000.4000 - 0x4003.4000 headers space (192KiB) + * 0x4000.4030 bin_hdr start address + * 0x4003.4000 - 0x4004.7c00 BootROM memory allocations (15KiB) + * 0x4007.fffc BootROM stack top + * + * The address space between 0x4007.fffc and 0x400f.fff is not locked in + * L2 cache thus cannot be used. + */ + +/* SPL */ +/* Defines for SPL */ +#define CONFIG_SPL_FRAMEWORK +#define CONFIG_SPL_TEXT_BASE 0x40004030 +#define CONFIG_SPL_MAX_SIZE ((128 << 10) - 0x4030) + +#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + (128 << 10)) +#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10) + +#ifdef CONFIG_SPL_BUILD +#define CONFIG_SYS_MALLOC_SIMPLE +#endif + +#define CONFIG_SPL_STACK (0x40000000 + ((192 - 16) << 10)) +#define CONFIG_SPL_BOOTROM_SAVE (CONFIG_SPL_STACK + 4) + +#define CONFIG_SPL_LIBCOMMON_SUPPORT +#define CONFIG_SPL_LIBGENERIC_SUPPORT +#define CONFIG_SPL_SERIAL_SUPPORT +#define CONFIG_SPL_I2C_SUPPORT + +/* SPL related SPI defines */ +#define CONFIG_SPL_SPI_SUPPORT +#define CONFIG_SPL_SPI_FLASH_SUPPORT +#define CONFIG_SPL_SPI_LOAD +#define CONFIG_SPL_SPI_BUS 0 +#define CONFIG_SPL_SPI_CS 0 +#define CONFIG_SYS_SPI_U_BOOT_OFFS 0x24000 + +/* DS414 bus width is 32bits */ +#define CONFIG_DDR_32BIT + +/* Use random ethernet address if not configured */ +#define CONFIG_LIB_RAND +#define CONFIG_NET_RANDOM_ETHADDR + +/* Default Environment */ +#define CONFIG_BOOTCOMMAND "sf read ${loadaddr} 0xd0000 0x700000; bootm" +#define CONFIG_BOOTARGS "console=ttyS0,115200" +#define CONFIG_LOADADDR 0x80000 +#undef CONFIG_PREBOOT /* override preboot for USB and SPI flash init */ +#define CONFIG_PREBOOT "usb start; sf probe" + +#endif /* _CONFIG_SYNOLOGY_DS414_H */ diff --git a/include/configs/maxbcm.h b/include/configs/maxbcm.h index da49243..43d7fd0 100644 --- a/include/configs/maxbcm.h +++ b/include/configs/maxbcm.h @@ -10,10 +10,6 @@ /* * High Level Configuration Options (easy to change) */ -#define CONFIG_ARMADA_XP /* SOC Family Name */ -#ifdef CONFIG_SPL_BUILD -#define CONFIG_SKIP_LOWLEVEL_INIT /* disable board lowlevel_init */ -#endif #define CONFIG_DISPLAY_BOARDINFO_LATE /* @@ -55,10 +51,7 @@ #define CONFIG_ENV_SECT_SIZE (64 << 10) /* 64KiB sectors */ #define CONFIG_PHY_MARVELL /* there is a marvell phy */ -#define CONFIG_PHY_ADDR { 0x0, 0x1, 0x2, 0x3 } -#define CONFIG_SYS_NETA_INTERFACE_TYPE PHY_INTERFACE_MODE_SGMII #define PHY_ANEG_TIMEOUT 8000 /* PHY needs a longer aneg time */ -#define CONFIG_RESET_PHY_R #define CONFIG_SYS_CONSOLE_INFO_QUIET /* don't print console @ startup */ #define CONFIG_SYS_ALT_MEMTEST @@ -91,9 +84,9 @@ #define CONFIG_SPL_BSS_START_ADDR (0x40000000 + (128 << 10)) #define CONFIG_SPL_BSS_MAX_SIZE (16 << 10) -#define CONFIG_SYS_SPL_MALLOC_START (CONFIG_SPL_BSS_START_ADDR + \ - CONFIG_SPL_BSS_MAX_SIZE) -#define CONFIG_SYS_SPL_MALLOC_SIZE (16 << 10) +#ifdef CONFIG_SPL_BUILD +#define CONFIG_SYS_MALLOC_SIMPLE +#endif #define CONFIG_SPL_STACK (0x40000000 + ((192 - 16) << 10)) #define CONFIG_SPL_BOOTROM_SAVE (CONFIG_SPL_STACK + 4) @@ -112,7 +105,7 @@ #define CONFIG_SYS_SPI_U_BOOT_OFFS 0x20000 /* Enable DDR support in SPL (DDR3 training from Marvell bin_hdr) */ -#define CONFIG_SYS_MVEBU_DDR_AXP #define CONFIG_DDR_FIXED_SIZE (1 << 20) /* 1GiB */ +#define CONFIG_BOARD_ECC_SUPPORT /* this board supports ECC */ #endif /* _CONFIG_DB_MV7846MP_GP_H */ diff --git a/tools/Makefile b/tools/Makefile index d49e40d..1382b05 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -156,7 +156,7 @@ ubsha1-objs := os_support.o ubsha1.o lib/sha1.o HOSTCFLAGS_ubsha1.o := -pedantic hostprogs-$(CONFIG_KIRKWOOD) += kwboot -hostprogs-$(CONFIG_ARMADA_XP) += kwboot +hostprogs-$(CONFIG_ARCH_MVEBU) += kwboot hostprogs-y += proftool hostprogs-$(CONFIG_STATIC_RELA) += relocate-rela diff --git a/tools/kwboot.c b/tools/kwboot.c index c5f4492..905ade3 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -9,10 +9,14 @@ * 2008. Chapter 24.2 "BootROM Firmware". */ +#include "kwbimage.h" +#include "mkimage.h" + #include <stdlib.h> #include <stdio.h> #include <string.h> #include <stdarg.h> +#include <image.h> #include <libgen.h> #include <fcntl.h> #include <errno.h> @@ -22,8 +26,6 @@ #include <sys/mman.h> #include <sys/stat.h> -#include "kwbimage.h" - #ifdef __GNUC__ #define PACKED __attribute((packed)) #else @@ -652,6 +654,14 @@ kwboot_img_patch_hdr(void *img, size_t size) hdr->blockid = IBR_HDR_UART_ID; + /* + * Subtract mkimage header size from destination address + * as this header is not expected by the Marvell BootROM. + * This way, the execution address is identical to the + * one the image is compiled for (TEXT_BASE). + */ + hdr->destaddr = hdr->destaddr - sizeof(struct image_header); + if (image_ver == 0) { struct main_hdr_v0 *hdr_v0 = img; |