From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5EC0AC433EF for ; Thu, 24 Mar 2022 22:05:13 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id C869284116; Thu, 24 Mar 2022 23:05:10 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="QSBCz9v6"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8438C84116; Thu, 24 Mar 2022 23:05:09 +0100 (CET) Received: from mail-yb1-xb35.google.com (mail-yb1-xb35.google.com [IPv6:2607:f8b0:4864:20::b35]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id C017984114 for ; Thu, 24 Mar 2022 23:05:00 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mibodhi@gmail.com Received: by mail-yb1-xb35.google.com with SMTP id e203so2054867ybc.12 for ; Thu, 24 Mar 2022 15:05:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=dIMCI8AHPecPt9xrX06ObyZdIDFZO92L+QtHOSlk/4A=; b=QSBCz9v6t/7CtjS2PqUJ2UWK+rrvLNx8rpoq5QCFFeSCTtv7wV4JEbfqnTZTOOVmkz ZNhmRpIx+VItFcI/aRcQ4sJbSp1gP/phkH1JG8KCRLThZhoZyoSKHn93r5lvyqSk0KdL eYXBaH3Hc2gh548mT17QuDXuvndfuLS/4z3RjkpivBZ2FCR4a2Tg0qajDHaUN+NMnjML nvKA6fKmL2w5mQrWiwFEvZdjHp6n2GY6Utlos3P0biLaAx5kSiMfbiFMaeX7z1ZUsoto UlLfIQbjuN1yVxyYRAXQlfYQnPvuQ9CPn78kbFOKasFBAUb55ZFM5kJvfNNetWiO3vcr LqFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=dIMCI8AHPecPt9xrX06ObyZdIDFZO92L+QtHOSlk/4A=; b=Dh8JmdvHLMsYquGBFaCSIIRDqhShqwQYd3ozGX8aG57rgvlStr+ZVMX03RoedBQHlS NNZc5jzgkQwMV16C1LHSiDS0LGyG8HcHTlsTXJbRViYC79hPSZkyW4gs6FdcQL9Gv7Vx JpwL1ZKhC5aojUHFRLb4aTZGtJcpIwujoDtw4J2ujPawT//DXpczhO40vS2d4y6zqSbi 2rNEgK611RjVCLhEStECWzkdhNCqyNlKpVJl4neUdH5oh/calfyR90WR6qp5Udyth/NJ 4J6ckb3W6493yN10WEh7UuYNDL4kwKjYiivpWwJBzCYwxWGrvLN4icY/ExxSAIlZdoOP vTfA== X-Gm-Message-State: AOAM530FTZ1qAm3FZTx/M9YGeA10IS8tNXiWml4e5tV9qJJ5Itk8gUap yd1LJn1FC+a8VVIXt8pBS/GW3LZNUcQVt3iSu50= X-Google-Smtp-Source: ABdhPJw67fT8UawgQrQpOk+nD6CdTEnkpqEaU9phqIiYUt0buDurDeunjVsjIhxPCBTWZ2bmcsN1AXDBzVnDatMpNfQ= X-Received: by 2002:a25:dc09:0:b0:633:88f0:8116 with SMTP id y9-20020a25dc09000000b0063388f08116mr6755620ybe.218.1648159499193; Thu, 24 Mar 2022 15:04:59 -0700 (PDT) MIME-Version: 1.0 References: <20220324101113.7msyxihxmbohfscw@pali> In-Reply-To: <20220324101113.7msyxihxmbohfscw@pali> From: Tony Dinh Date: Thu, 24 Mar 2022 15:04:47 -0700 Message-ID: Subject: Re: [PATCH] arm: kirkwood: Add nas440 board, Marvell 88SE6121 AHCI To: =?UTF-8?Q?Pali_Roh=C3=A1r?= , Stefan Roese Cc: Hajo Noerenberg , U-Boot Mailing List Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean Hi Hajo, I've added Stefan. When you send patches for Kirkwood or other Marvell boards, please also send it directly to Stefan (Stefan is the maintainer of Marvell u-boots). Tony On Thu, Mar 24, 2022 at 3:11 AM Pali Roh=C3=A1r wrote: > > Hello! > > On Thursday 24 March 2022 10:55:38 Hajo Noerenberg wrote: > > This adds support for the Seagate Blackarmor NAS440 (4-bay Kirkwood NAS= box). > > > > Does it make sense to include support for a 10+ year old device? > > If these old devices are still in use and you would like to maintain > this support then I think that there is no issue with it. > > > If yes, I would be willing to discuss and finalize this patch. If no, i= t will be archived here for the public, which is fine with me. > > > > For the NAS440 is the something special that hard disk drives 1 and 2 a= re connected to a 88SE6121 SATA-II controller, which is connected via PCIe.= Hard disk drives 3 and 4 are directly connected to the 88F6281 SoC. > > > > - Add NAS440 dtb and associated files/configs > > * Includes support for HD44780 front LCD > > * Includes support for device LEDs (via 74AHC164 shift register) > > - Add Marvell 88SE6121 AHCI support. Thanks to Pali Roh=C3=A1r for rece= ntly adding the necessary Kirkwood PCIe driver. It works :) > > Perfect! > > > - Tested with my NAS440 hardware: ETH/USB/SATA/AHCI-SCSI/GPIO/LCD/LEDs = ok > > > > As far as I can see this fully implements the support for this board wi= thin U-Boot. With the Linux kernel however there are problems, the kernel A= HCI driver fails with "failed to IDENTIFY" messages for the 88SE6121 drive = ports, which I could not solve yet despite comparison with the GPL sources = from Seagate. > > > > Note: I am collecting various information and patches for the family of= Blackarmor NAS boards at https://github.com/hn/seagate-blackarmor-nas > > > > Hajo > > > > > > --- > > arch/arm/dts/kirkwood-blackarmor-nas440.dts | 166 +++++++++ > > board/Seagate/nas440/Kconfig | 12 + > > board/Seagate/nas440/MAINTAINERS | 7 + > > board/Seagate/nas440/Makefile | 7 + > > board/Seagate/nas440/kwbimage.cfg | 156 ++++++++ > > board/Seagate/nas440/nas440.c | 378 ++++++++++++++++++++ > > configs/nas440_defconfig | 89 +++++ > > drivers/ata/ahci-pci.c | 1 + > > include/configs/nas440.h | 50 +++ > > 9 files changed, 866 insertions(+) > > create mode 100644 arch/arm/dts/kirkwood-blackarmor-nas440.dts > > create mode 100644 board/Seagate/nas440/Kconfig > > create mode 100644 board/Seagate/nas440/MAINTAINERS > > create mode 100644 board/Seagate/nas440/Makefile > > create mode 100644 board/Seagate/nas440/kwbimage.cfg > > create mode 100644 board/Seagate/nas440/nas440.c > > create mode 100644 configs/nas440_defconfig > > create mode 100644 include/configs/nas440.h > > > > diff --git a/arch/arm/dts/kirkwood-blackarmor-nas440.dts b/arch/arm/dts= /kirkwood-blackarmor-nas440.dts > > new file mode 100644 > > index 0000000000..60e3fe6f0d > > --- /dev/null > > +++ b/arch/arm/dts/kirkwood-blackarmor-nas440.dts > > @@ -0,0 +1,166 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > +/* > > + * Device Tree file for Seagate Blackarmor NAS440 > > + * > > + * Copyright (C) 2021 Hajo Noerenberg > > + * Copyright (C) 2015 Andreas Fischer > > + * Copyright (C) 2014 Evgeni Dobrev > > + */ > > + > > +/dts-v1/; > > + > > +#include > > +#include > > +#include "kirkwood.dtsi" > > +#include "kirkwood-6281.dtsi" > > + > > +/ { > > + model =3D "Seagate Blackarmor NAS440"; > > + compatible =3D "seagate,blackarmor-nas440","marvell,kirkwood-88f6= 281", > > + "marvell,kirkwood"; > > + > > + memory { /* 256 MB */ > > + device_type =3D "memory"; > > + reg =3D <0x00000000 0x10000000>; > > + }; > > + > > + chosen { > > + bootargs =3D "console=3DttyS0,115200n8"; > > + stdout-path =3D &uart0; > > + }; > > + > > + gpio_poweroff { > > + compatible =3D "gpio-poweroff"; > > + gpios =3D <&gpio1 16 GPIO_ACTIVE_LOW>; /* GPIO= 1-16 is MPP48 */ > > + }; > > + > > + gpio_keys { > > + compatible =3D "gpio-keys"; > > + > > + reset { > > + label =3D "Reset"; > > + linux,code =3D ; > > + gpios =3D <&gpio0 29 GPIO_ACTIVE_LOW>; > > + }; > > + > > + button { > > + label =3D "Power"; > > + linux,code =3D ; > > + gpios =3D <&gpio1 17 GPIO_ACTIVE_LOW>; /* GPIO= 1-17 is MPP49 */ > > + }; > > + }; > > + > > + regulators { > > + compatible =3D "simple-bus"; > > + #address-cells =3D <1>; > > + #size-cells =3D <0>; > > + pinctrl-0 =3D <&pmx_power_socsata>; > > + pinctrl-names =3D "default"; > > + > > + socsata_power: regulator@1 { > > + compatible =3D "regulator-fixed"; > > + reg =3D <1>; > > + regulator-name =3D "SoC SATA Power"; > > + regulator-min-microvolt =3D <12000000>; > > + regulator-max-microvolt =3D <12000000>; > > + enable-active-high; > > + regulator-always-on; > > + regulator-boot-on; > > + gpio =3D <&gpio0 28 GPIO_ACTIVE_HIGH>; > > + }; > > + }; > > +}; > > + > > +/* > > + * Serial port routed to connector CN4 > > + * > > + * pin 1 - TX (CPU's TX) > > + * pin 4 - RX (CPU's RX) > > + * pin 6 - GND > > + */ > > +&uart0 { > > + status =3D "okay"; > > +}; > > + > > +&pinctrl { > > + pinctrl-0 =3D <&pmx_button_reset &pmx_button_power>; > > + pinctrl-names =3D "default"; > > + > > + pmx_act_sata0: pmx-act-sata0 { > > + marvell,pins =3D "mpp15"; > > + marvell,function =3D "sata0"; > > + }; > > + > > + pmx_act_sata1: pmx-act-sata1 { > > + marvell,pins =3D "mpp16"; > > + marvell,function =3D "sata1"; > > + }; > > + > > + pmx_power_socsata: pmx-power-socsata { > > + marvell,pins =3D "mpp28"; > > + marvell,function =3D "gpio"; > > + }; > > + > > + pmx_button_reset: pmx-button-reset { > > + marvell,pins =3D "mpp29"; > > + marvell,function =3D "gpio"; > > + }; > > + > > + pmx_button_power: pmx-button-power { > > + marvell,pins =3D "mpp49"; > > + marvell,function =3D "gpio"; > > + }; > > +}; > > + > > +&sata { > > + status =3D "okay"; > > + nr-ports =3D <2>; > > +}; > > + > > +&pciec { > > + status =3D "okay"; > > +}; > > + > > +&pcie0 { > > + status =3D "okay"; > > +}; > > + > > +&i2c0 { > > + status =3D "okay"; > > + > > + adt7473: thermal@2e { > > + compatible =3D "adi,adt7473"; > > + reg =3D <0x2e>; > > + }; > > +}; > > + > > +&nand { > > + status =3D "okay"; > > +}; > > + > > +&mdio { > > + status =3D "okay"; > > + > > + ethphy0: ethernet-phy@8 { > > + reg =3D <8>; > > + }; > > + ethphy1: ethernet-phy@9 { > > + reg =3D <9>; > > + }; > > +}; > > + > > +ð0 { > > + status =3D "okay"; > > + > > + ethernet0-port@0 { > > + phy-handle =3D <ðphy0>; > > + }; > > +}; > > + > > +ð1 { > > + status =3D "okay"; > > + > > + ethernet1-port@0 { > > + phy-handle =3D <ðphy1>; > > + }; > > +}; > > diff --git a/board/Seagate/nas440/Kconfig b/board/Seagate/nas440/Kconfi= g > > new file mode 100644 > > index 0000000000..3f93d75cd4 > > --- /dev/null > > +++ b/board/Seagate/nas440/Kconfig > > @@ -0,0 +1,12 @@ > > +if TARGET_NAS440 > > + > > +config SYS_BOARD > > + default "nas440" > > + > > +config SYS_VENDOR > > + default "Seagate" > > + > > +config SYS_CONFIG_NAME > > + default "nas440" > > + > > +endif > > diff --git a/board/Seagate/nas440/MAINTAINERS b/board/Seagate/nas440/MA= INTAINERS > > new file mode 100644 > > index 0000000000..dcea1316c5 > > --- /dev/null > > +++ b/board/Seagate/nas440/MAINTAINERS > > @@ -0,0 +1,7 @@ > > +NAS440 BOARD > > +M: Hajo Noerenberg > > +S: Maintained > > +F: board/Seagate/nas440/ > > +F: include/configs/nas440.h > > +F: configs/nas440_defconfig > > +F: arch/arm/dts/kirkwood-blackarmor-nas440.dts > > diff --git a/board/Seagate/nas440/Makefile b/board/Seagate/nas440/Makef= ile > > new file mode 100644 > > index 0000000000..2a3ef746d3 > > --- /dev/null > > +++ b/board/Seagate/nas440/Makefile > > @@ -0,0 +1,7 @@ > > +# > > +# Copyright (C) 2014 Evgeni Dobrev > > +# > > +# SPDX-License-Identifier: GPL-2.0+ > > +# > > + > > +obj-y :=3D nas440.o > > diff --git a/board/Seagate/nas440/kwbimage.cfg b/board/Seagate/nas440/k= wbimage.cfg > > new file mode 100644 > > index 0000000000..e71da11694 > > --- /dev/null > > +++ b/board/Seagate/nas440/kwbimage.cfg > > @@ -0,0 +1,156 @@ > > +# > > +# Copyright (C) 2021 Hajo Noerenberg > > +# > > +# Based on nas220/kwbimage.cfg originally written by > > +# Evgeni Dobrev > > +# > > +# Based on sheevaplug/kwbimage.cfg originally written by > > +# Prafulla Wadaskar > > +# (C) Copyright 2009 > > +# Marvell Semiconductor > > +# > > +# SPDX-License-Identifier: GPL-2.0+ > > +# > > +# Refer doc/README.kwbimage for more details about how-to configure > > +# and create kirkwood boot image > > +# > > + > > +# Boot Media configurations > > +BOOT_FROM nand > > +NAND_ECC_MODE default > > +NAND_PAGE_SIZE 0x0200 > > + > > +# SOC registers configuration using bootrom header extension > > +# Maximum KWBIMAGE_MAX_CONFIG configurations allowed > > + > > +# Configure RGMII-0 interface pad voltage to 1.8V > > +DATA 0xFFD100E0 0x1B1B1B9B > > + > > +DATA 0xFFD20134 0xBBBBBBBB > > +DATA 0xFFD20138 0x00BBBBBB > > + > > +#Dram initalization for SINGLE x16 CL=3D5 @ 400MHz > > +DATA 0xFFD01400 0x43000C30 # DDR Configuration register > > +# bit13-0: 0xa00 (2560 DDR2 clks refresh rate) > > +# bit23-14: zero > > +# bit24: 1=3D enable exit self refresh mode on DDR access > > +# bit25: 1 required > > +# bit29-26: zero > > +# bit31-30: 01 > > + > > +DATA 0xFFD01404 0x39543000 # DDR Controller Control Low > > +# bit 4: 0=3Daddr/cmd in smame cycle > > +# bit 5: 0=3Dclk is driven during self refresh, we don't care for A= PX > > +# bit 6: 0=3Duse recommended falling edge of clk for addr/cmd > > +# bit14: 0=3Dinput buffer always powered up > > +# bit18: 1=3Dcpu lock transaction enabled > > +# bit23-20: 5=3Drecommended value for CL=3D5 and STARTBURST_DEL disabl= ed bit31=3D0 > > +# bit27-24: 8=3D CL+3, STARTBURST sample stages, for freqs 400MHz, unb= uffered DIMM > > +# bit30-28: 3 required > > +# bit31: 0=3Dno additional STARTBURST delay > > + > > +DATA 0xFFD01408 0x22125451 # DDR Timing (Low) (active cycles value += 1) > > +# bit7-4: TRCD > > +# bit11- 8: TRP > > +# bit15-12: TWR > > +# bit19-16: TWTR > > +# bit20: TRAS msb > > +# bit23-21: 0x0 > > +# bit27-24: TRRD > > +# bit31-28: TRTP > > + > > +DATA 0xFFD0140C 0x00000833 # DDR Timing (High) > > +# bit6-0: TRFC > > +# bit8-7: TR2R > > +# bit10-9: TR2W > > +# bit12-11: TW2W > > +# bit31-13: zero required > > + > > +DATA 0xFFD01410 0x0000000C # DDR Address Control > > +# bit1-0: 00, Cs0width=3Dx8 > > +# bit3-2: 11, Cs0size=3D1Gb > > +# bit5-4: 00, Cs1width=3Dnonexistent > > +# bit7-6: 00, Cs1size =3Dnonexistent > > +# bit9-8: 00, Cs2width=3Dnonexistent > > +# bit11-10: 00, Cs2size =3Dnonexistent > > +# bit13-12: 00, Cs3width=3Dnonexistent > > +# bit15-14: 00, Cs3size =3Dnonexistent > > +# bit16: 0, Cs0AddrSel > > +# bit17: 0, Cs1AddrSel > > +# bit18: 0, Cs2AddrSel > > +# bit19: 0, Cs3AddrSel > > +# bit31-20: 0 required > > + > > +DATA 0xFFD01414 0x00000000 # DDR Open Pages Control > > +# bit0: 0, OpenPage enabled > > +# bit31-1: 0 required > > + > > +DATA 0xFFD01418 0x00000000 # DDR Operation > > +# bit3-0: 0x0, DDR cmd > > +# bit31-4: 0 required > > + > > +DATA 0xFFD0141C 0x00000C52 # DDR Mode > > +# bit2-0: 2, BurstLen=3D2 required > > +# bit3: 0, BurstType=3D0 required > > +# bit6-4: 4, CL=3D5 > > +# bit7: 0, TestMode=3D0 normal > > +# bit8: 0, DLL reset=3D0 normal > > +# bit11-9: 6, auto-precharge write recovery ???????????? > > +# bit12: 0, PD must be zero > > +# bit31-13: 0 required > > + > > +DATA 0xFFD01420 0x00000042 # DDR Extended Mode > > +# bit0: 0, DDR DLL enabled > > +# bit1: 0, DDR drive strenght normal > > +# bit2: 0, DDR ODT control lsd (disabled) > > +# bit5-3: 000, required > > +# bit6: 1, DDR ODT control msb, (disabled) > > +# bit9-7: 000, required > > +# bit10: 0, differential DQS enabled > > +# bit11: 0, required > > +# bit12: 0, DDR output buffer enabled > > +# bit31-13: 0 required > > + > > +DATA 0xFFD01424 0x0000F1FF # DDR Controller Control High > > +# bit2-0: 111, required > > +# bit3 : 1 , MBUS Burst Chop disabled > > +# bit6-4: 111, required > > +# bit7 : 0 > > +# bit8 : 0 > > +# bit9 : 0 , no half clock cycle addition to dataout > > +# bit10 : 0 , 1/4 clock cycle skew enabled for addr/ctl signals > > +# bit11 : 0 , 1/4 clock cycle skew disabled for write mesh > > +# bit15-12: 1111 required > > +# bit31-16: 0 required > > + > > +DATA 0xFFD01428 0x00085520 > > +DATA 0xFFD0147C 0x00008552 > > + > > +DATA 0xFFD01504 0x0FFFFFF1 # CS[0]n Size > > +# bit0: 1, Window enabled > > +# bit1: 0, Write Protect disabled > > +# bit3-2: 00, CS0 hit selected > > +# bit23-4: ones, required > > +# bit31-24: 0x07, Size (i.e. 128MB) > > + > > +DATA 0xFFD01508 0x00000000 # CS[1]n Base address to 0x0 > > + > > +DATA 0xFFD0150C 0x00000000 # CS[1]n Size, window disabled > > + > > +DATA 0xFFD01514 0x00000000 # CS[2]n Size, window disabled > > +DATA 0xFFD0151C 0x00000000 # CS[3]n Size, window disabled > > + > > +DATA 0xFFD01494 0x003C0000 # DDR ODT Control (Low) > > +DATA 0xFFD01498 0x00000000 # DDR ODT Control (High) > > +# bit1-0: 00, ODT0 controlled by ODT Control (low) register above > > +# bit3-2: 01, ODT1 active NEVER! > > +# bit31-4: zero, required > > + > > +DATA 0xFFD0149C 0x0000F80F # CPU ODT Control > > + > > +DATA 0xFFD01480 0x00000001 # DDR Initialization Control > > +#bit0=3D1, enable DDR init upon this register write > > + > > +# End of Header extension > > +DATA 0x0 0x0 > > + > > diff --git a/board/Seagate/nas440/nas440.c b/board/Seagate/nas440/nas44= 0.c > > new file mode 100644 > > index 0000000000..43a08e61bf > > --- /dev/null > > +++ b/board/Seagate/nas440/nas440.c > > @@ -0,0 +1,378 @@ > > +/* > > + * Copyright (C) 2022 Hajo Noerenberg > > + * > > + * Based on nas220.c originally written by > > + * Evgeni Dobrev > > + * > > + * Based on sheevaplug.c originally written by > > + * Prafulla Wadaskar > > + * (C) Copyright 2009 > > + * Marvell Semiconductor > > + * > > + * SPDX-License-Identifier: GPL-2.0+ > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +DECLARE_GLOBAL_DATA_PTR; > > + > > +/* > > + * GPIO pin names, input/output direction and default values > > + * > > + * NAS440_GPIO_BUTTON_LCD_LOWER, NAS440_GPIO_BUTTON_LCD_UPPER > > + * Buttons next to LC display, LOW if pressed > > + * > > + * NAS440_GPIO_BUTTON_POWER > > + * Power button at front of case, LOW if pressed > > + * > > + * NAS440_GPIO_BUTTON_RESET > > + * Reset button at back of case, LOW if pressed > > + * > > + * NAS440_GPIO_LCD_HD44780_* > > + * HD44780-compatible LC display, control via 8bit parallel data tran= sfer > > + * > > + * NAS440_GPIO_LED_74AHC164_* > > + * Control front panel LEDs via 74AHC164 8bit shift register > > + * > > + * NAS440_GPIO_SOCSATA_POWER > > + * 12V Power for SoC SATA ports (NAS drives 3 and 4) > > + * > > + * NAS440_GPIO_BOARD_POWER > > + * Shutdown board if LOW > > + * > > + */ > > + > > +#define NAS440_GPIO_LCD_HD44780_BACKLIGHT 7 > > +#define NAS440_GPIO_LED_74AHC164_DATA 12 > > +#define NAS440_GPIO_LED_74AHC164_CLK 13 > > +#define NAS440_GPIO_SOCSATA_POWER 28 > > +#define NAS440_GPIO_BUTTON_RESET 29 > > +#define NAS440_GPIO_BUTTON_LCD_LOWER 34 > > +#define NAS440_GPIO_LCD_HD44780_RS 35 > > +#define NAS440_GPIO_LCD_HD44780_D0 36 > > +#define NAS440_GPIO_LCD_HD44780_D1 37 > > +#define NAS440_GPIO_LCD_HD44780_D2 38 > > +#define NAS440_GPIO_LCD_HD44780_D3 39 > > +#define NAS440_GPIO_LCD_HD44780_D4 40 > > +#define NAS440_GPIO_LCD_HD44780_D5 41 > > +#define NAS440_GPIO_LCD_HD44780_D6 42 > > +#define NAS440_GPIO_LCD_HD44780_D7 43 > > +#define NAS440_GPIO_LCD_HD44780_RW 44 > > +#define NAS440_GPIO_LCD_HD44780_E 45 > > +#define NAS440_GPIO_BUTTON_LCD_UPPER 47 > > +#define NAS440_GPIO_BOARD_POWER 48 > > +#define NAS440_GPIO_BUTTON_POWER 49 > > + > > +/* > > + * GPIO output enable, pins 0-31 to LOW, pins 31-49 to HIGH config reg= ister > > + */ > > +#define NAS440_GE_OE_LOW (~(BIT(NAS440_GPIO_LCD_HD44780_BACKLIGHT)= \ > > + | BIT(NAS440_GPIO_LED_74AHC164_DATA) = \ > > + | BIT(NAS440_GPIO_LED_74AHC164_CLK) = \ > > + | BIT(NAS440_GPIO_SOCSATA_POWER))) > > +#define NAS440_GE_OE_HIGH (~(BIT_MASK(NAS440_GPIO_BOARD_POWER) = \ > > + | BIT_MASK(NAS440_GPIO_LCD_HD44780_RS) = \ > > + | BIT_MASK(NAS440_GPIO_LCD_HD44780_D0) = \ > > + | BIT_MASK(NAS440_GPIO_LCD_HD44780_D1) = \ > > + | BIT_MASK(NAS440_GPIO_LCD_HD44780_D2) = \ > > + | BIT_MASK(NAS440_GPIO_LCD_HD44780_D3) = \ > > + | BIT_MASK(NAS440_GPIO_LCD_HD44780_D4) = \ > > + | BIT_MASK(NAS440_GPIO_LCD_HD44780_D5) = \ > > + | BIT_MASK(NAS440_GPIO_LCD_HD44780_D6) = \ > > + | BIT_MASK(NAS440_GPIO_LCD_HD44780_D7) = \ > > + | BIT_MASK(NAS440_GPIO_LCD_HD44780_RW) = \ > > + | BIT_MASK(NAS440_GPIO_LCD_HD44780_E))) > > + > > +/* > > + * GPIO output default values > > + */ > > +#define NAS440_GE_OE_VAL_LOW BIT(NAS440_GPIO_LCD_HD44780_BACKLIGHT) > > + > > +#define NAS440_GE_OE_VAL_HIGH BIT_MASK(NAS440_GPIO_BOARD_POWER) > > + > > +int board_early_init_f(void) > > +{ > > + /* > > + * default gpio configuration > > + */ > > + mvebu_config_gpio(NAS440_GE_OE_VAL_LOW, NAS440_GE_OE_VAL_HIGH, > > + NAS440_GE_OE_LOW, NAS440_GE_OE_HIGH); > > + > > + /* Multi-Purpose Pins Functionality configuration */ > > + static const u32 kwmpp_config[] =3D { > > + MPP0_NF_IO2, > > + MPP1_NF_IO3, > > + MPP2_NF_IO4, > > + MPP3_NF_IO5, > > + MPP4_NF_IO6, > > + MPP5_NF_IO7, > > + MPP6_SYSRST_OUTn, > > + MPP7_GPO, /* NAS440_GPIO_LCD_HD44780_BACKLI= GHT */ > > + MPP8_TW_SDA, > > + MPP9_TW_SCK, > > + MPP10_UART0_TXD, > > + MPP11_UART0_RXD, > > + MPP12_GPO, /* NAS440_GPIO_LED_74AHC164_DATA = */ > > + MPP13_GPIO, /* NAS440_GPIO_LED_74AHC164_CLK *= / > > + MPP14_SATA1_PRESENTn, > > + MPP15_SATA0_ACTn, > > + MPP16_SATA1_ACTn, > > + MPP17_SATA0_PRESENTn, > > + MPP18_NF_IO0, > > + MPP19_NF_IO1, > > + MPP20_GE1_0, /* GbE Port1, RGMII mode (12 pins= GE1_0-7, GE1_10-13) */ > > + MPP21_GE1_1, > > + MPP22_GE1_2, > > + MPP23_GE1_3, > > + MPP24_GE1_4, > > + MPP25_GE1_5, > > + MPP26_GE1_6, > > + MPP27_GE1_7, > > + MPP28_GPIO, /* NAS440_GPIO_SOCSATA_POWER */ > > + MPP29_GPIO, /* NAS440_GPIO_BUTTON_RESET */ > > + MPP30_GE1_10, > > + MPP31_GE1_11, > > + MPP32_GE1_12, > > + MPP33_GE1_13, > > + MPP34_GPIO, /* NAS440_GPIO_BUTTON_LCD_LOWER *= / > > + MPP35_GPIO, /* NAS440_GPIO_LCD_HD44780_RS */ > > + MPP36_GPIO, /* NAS440_GPIO_LCD_HD44780_D0 */ > > + MPP37_GPIO, /* NAS440_GPIO_LCD_HD44780_D1 */ > > + MPP38_GPIO, /* NAS440_GPIO_LCD_HD44780_D2 */ > > + MPP39_GPIO, /* NAS440_GPIO_LCD_HD44780_D3 */ > > + MPP40_GPIO, /* NAS440_GPIO_LCD_HD44780_D4 */ > > + MPP41_GPIO, /* NAS440_GPIO_LCD_HD44780_D5 */ > > + MPP42_GPIO, /* NAS440_GPIO_LCD_HD44780_D6 */ > > + MPP43_GPIO, /* NAS440_GPIO_LCD_HD44780_D7 */ > > + MPP44_GPIO, /* NAS440_GPIO_LCD_HD44780_RW */ > > + MPP45_GPIO, /* NAS440_GPIO_LCD_HD44780_E */ > > + MPP46_GPIO, > > + MPP47_GPIO, /* NAS440_GPIO_BUTTON_LCD_UPPER *= / > > + MPP48_GPIO, /* NAS440_GPIO_BOARD_POWER */ > > + MPP49_GPIO, /* NAS440_GPIO_BUTTON_POWER */ > > + 0 > > + }; > > + kirkwood_mpp_conf(kwmpp_config, NULL); > > + return 0; > > +} > > + > > +/* HD44780 pins, data bits first, backlight last */ > > +static int hd44780_pins[12] =3D { > > + NAS440_GPIO_LCD_HD44780_D0, > > + NAS440_GPIO_LCD_HD44780_D1, > > + NAS440_GPIO_LCD_HD44780_D2, > > + NAS440_GPIO_LCD_HD44780_D3, > > + NAS440_GPIO_LCD_HD44780_D4, > > + NAS440_GPIO_LCD_HD44780_D5, > > + NAS440_GPIO_LCD_HD44780_D6, > > + NAS440_GPIO_LCD_HD44780_D7, > > + NAS440_GPIO_LCD_HD44780_E, > > + NAS440_GPIO_LCD_HD44780_RW, > > + NAS440_GPIO_LCD_HD44780_RS, > > + NAS440_GPIO_LCD_HD44780_BACKLIGHT > > +}; > > + > > +#define HD44780_NUM_COL 16 > > +#define HD44780_BUF_COL 40 > > +#define HD44780_NUM_ROW 2 > > + > > +#define HD44780_PIN_NUM (sizeof(hd44780_pins)/siz= eof(int)) > > + > > +/* > > + * HD44780 LCD display commands - adapted from hd44780.h by Joerg Wuns= ch > > + * > > + * -------------------------------------------------------------------= --------- > > + * "THE BEER-WARE LICENSE" (Revision 42): > > + * wrote this file. As long as you retain this no= tice you > > + * can do whatever you want with this stuff. If we meet some day, and = you think > > + * this stuff is worth it, you can buy me a beer in return. Joe= rg Wunsch > > + * -------------------------------------------------------------------= --------- > > + */ > > + > > +#define HD44780_CMD_CLR \ > > + 0x01 > > +#define HD44780_CMD_HOME \ > > + 0x02 > > +#define HD44780_CMD_ENTMODE(inc, shift) \ > > + (0x04 | ((inc)? 0x02: 0) | ((shift)? 1: 0)) > > +#define HD44780_CMD_DISPCTL(disp, cursor, blink) \ > > + (0x08 | ((disp)? 0x04: 0) | ((cursor)? 0x02: 0) | ((blink)? 1: 0)= ) > > +#define HD44780_CMD_SHIFT(shift, right) \ > > + (0x10 | ((shift)? 0x08: 0) | ((right)? 0x04: 0)) > > +#define HD44780_CMD_FNSET(if8bit, twoline, font5x10) \ > > + (0x20 | ((if8bit)? 0x10: 0) | ((twoline)? 0x08: 0) | \ > > + ((font5x10)? 0x04: 0)) > > +#define HD44780_CMD_CGADDR(addr) \ > > + (0x40 | ((addr) & 0x3f)) > > +#define HD44780_CMD_DDADDR(addr) \ > > + (0x80 | ((addr) & 0x7f)) > > + > > +static void lcd_send(unsigned int val, int mode) > > +{ > > + udelay(1); > > + kw_gpio_set_value(NAS440_GPIO_LCD_HD44780_RS, mode); > > + udelay(1); > > + > > + kw_gpio_set_value(NAS440_GPIO_LCD_HD44780_E, 0); > > + for (int i=3D0; i<8; i++) { > > + kw_gpio_set_value(hd44780_pins[i], (val&(1<>i ); > > + } > > + udelay(1); > > + kw_gpio_set_value(NAS440_GPIO_LCD_HD44780_E, 1); > > + udelay(1); > > + kw_gpio_set_value(NAS440_GPIO_LCD_HD44780_E, 0); > > + udelay(50); > > +} > > + > > +void lcd_init(void) > > +{ > > + for (int i=3D0; i > + kw_gpio_set_valid(hd44780_pins[i], GPIO_OUTPUT_OK); > > + kw_gpio_direction_output(hd44780_pins[i], i =3D=3D (HD447= 80_PIN_NUM-1)); > > + } > > + > > + lcd_send(HD44780_CMD_FNSET(1, 1, 0), 0); > > + udelay(50); > > + lcd_send(HD44780_CMD_FNSET(1, 1, 0), 0); > > + udelay(50); > > + lcd_send(HD44780_CMD_FNSET(1, 1, 0), 0); > > + udelay(50); > > + lcd_send(HD44780_CMD_DISPCTL(1, 0, 0), 0); > > + udelay(50); > > + lcd_send(HD44780_CMD_CLR, 0); > > + udelay(50); > > + lcd_send(HD44780_CMD_ENTMODE(1, 0), 0); > > + > > + udelay(2000); > > +} > > + > > +void lcd_row(int row, char *buf) > > +{ > > + int p =3D 0; > > + > > + if (row >=3D HD44780_NUM_ROW) { > > + return; > > + } > > + > > + lcd_send(HD44780_CMD_DDADDR(HD44780_BUF_COL * row + 0), 0); > > + for (int i=3D0; i > + if (buf[i] =3D=3D 0) { > > + p++; > > + } > > + lcd_send(p ? 32 : buf[i], 1); > > + } > > +} > > + > > +enum led_disk { > > + LED_DSK_OFF, > > + LED_DSK_RED > > + /* LED_DSK_GREEN disk activity led is controlled directly by the = hardware */ > > +}; > > + > > +enum led_system { > > + LED_SYS_OFF, > > + LED_SYS_BLUE, > > + LED_SYS_RED > > +}; > > + > > +void led_init(void) > > +{ > > + kw_gpio_set_valid(NAS440_GPIO_LED_74AHC164_DATA, GPIO_OUTPUT_OK); > > + kw_gpio_direction_output(NAS440_GPIO_LED_74AHC164_DATA, 0); > > + kw_gpio_set_valid(NAS440_GPIO_LED_74AHC164_CLK, GPIO_OUTPUT_OK); > > + kw_gpio_direction_output(NAS440_GPIO_LED_74AHC164_CLK, 0); > > +} > > + > > +void led_set(enum led_disk disk1, enum led_disk disk2, enum led_disk d= isk3, > > + enum led_disk disk4, enum led_system front1 ) > > +{ > > + int ledbits =3D (0x81 | ((front1=3D=3DLED_SYS_RED)? 0x08 : 0) | (= (front1=3D=3DLED_SYS_BLUE)? 0x04 : 0) \ > > + | ((disk1=3D=3DLED_DSK_RED)? 0 : 0x02) | ((disk2=3D=3DLED= _DSK_RED)? 0 : 0x40) \ > > + | ((disk3=3D=3DLED_DSK_RED)? 0 : 0x20) | ((disk4=3D=3DLED= _DSK_RED)? 0 : 0x10)); > > + > > + for (int i=3D0; i<8; i++) { > > + kw_gpio_set_value(NAS440_GPIO_LED_74AHC164_DATA, (ledbits= >> i) & 1); > > + udelay(1); > > + kw_gpio_set_value(NAS440_GPIO_LED_74AHC164_CLK, 1); > > + kw_gpio_set_value(NAS440_GPIO_LED_74AHC164_CLK, 0); > > + } > > +} > > + > > +/* factory firmware delays hard disk spinup, presumably to avoid power= peaks */ > > +void delay_hdd_spinup(void) > > +{ > > + lcd_row(1, "Delay HDD spinup"); > > + > > + for (int i =3D 0; i<2500; i++) { > > + udelay(1000); > > + } > > + > > + kw_gpio_set_valid(NAS440_GPIO_SOCSATA_POWER, GPIO_OUTPUT_OK); > > + kw_gpio_direction_output(NAS440_GPIO_SOCSATA_POWER, 1); > > +} > > + > > +#if CONFIG_IS_ENABLED(BOOTSTAGE) > > +void show_boot_progress(int val) > > +{ > > + switch (val) { > > +/* 0123456789abcdef */ > > + case BOOTSTAGE_ID_BOARD_INIT_DONE: > > + lcd_row(1, "Board init done"); > > + break; > > + case BOOTSTAGE_ID_USB_START: > > + lcd_row(1, "Init USB"); > > + break; > > + case BOOTSTAGE_ID_ETH_START: > > + lcd_row(1, "Init ethernet"); > > + break; > > + case BOOTSTAGE_ID_MAIN_LOOP: > > + lcd_row(1, "Wait for input"); > > + break; > > + case BOOTSTAGE_ID_RUN_OS: > > + lcd_row(1, "Starting Linux"); > > + break; > > + default: > > + if (val < 0) /* error */ > > + lcd_row(1, "Error"); > > + break; > > + } > > +} > > +#endif > > + > > +int board_eth_init(struct bd_info *bis) > > +{ > > + return cpu_eth_init(bis); > > +} > > + > > +int board_init(void) > > +{ > > + /* > > + * arch number of board > > + */ > > + gd->bd->bi_arch_number =3D MACH_TYPE_DB88F6281_BP; > > + > > + /* adress of boot parameters */ > > + gd->bd->bi_boot_params =3D mvebu_sdram_bar(0) + 0x100; > > + > > + led_init(); > > + led_set(LED_DSK_OFF, LED_DSK_OFF, LED_DSK_OFF, LED_DSK_OFF, LED_S= YS_BLUE); > > + > > + lcd_init(); > > + lcd_row(0, U_BOOT_VERSION ""); > > + > > + delay_hdd_spinup(); > > + > > + return 0; > > +} > > diff --git a/configs/nas440_defconfig b/configs/nas440_defconfig > > new file mode 100644 > > index 0000000000..74faf1a24b > > --- /dev/null > > +++ b/configs/nas440_defconfig > > @@ -0,0 +1,89 @@ > > +CONFIG_ARM=3Dy > > +CONFIG_SKIP_LOWLEVEL_INIT=3Dy > > +CONFIG_SYS_DCACHE_OFF=3Dy > > +CONFIG_ARCH_CPU_INIT=3Dy > > +CONFIG_ARCH_KIRKWOOD=3Dy > > +CONFIG_SUPPORT_PASSING_ATAGS=3Dy > > +CONFIG_CMDLINE_TAG=3Dy > > +CONFIG_INITRD_TAG=3Dy > > +CONFIG_SYS_KWD_CONFIG=3D"board/Seagate/nas440/kwbimage.cfg" > > +CONFIG_SYS_TEXT_BASE=3D0x600000 > > +CONFIG_NR_DRAM_BANKS=3D2 > > +CONFIG_TARGET_NAS440=3Dy > > +CONFIG_ENV_SIZE=3D0x10000 > > +CONFIG_ENV_OFFSET=3D0xA0000 > > +CONFIG_DEFAULT_DEVICE_TREE=3D"kirkwood-blackarmor-nas440" > > +CONFIG_IDENT_STRING=3D"\nNAS 440" > > +# CONFIG_SYS_MALLOC_F is not set > > +CONFIG_SYS_LOAD_ADDR=3D0x800000 > > +CONFIG_SHOW_BOOT_PROGRESS=3Dy > > +CONFIG_BOOTSTAGE=3Dy > > +CONFIG_BOOTDELAY=3D3 > > +CONFIG_USE_PREBOOT=3Dy > > +CONFIG_PREBOOT=3D"pci enum; " > > +# CONFIG_DISPLAY_BOARDINFO is not set > > +CONFIG_HUSH_PARSER=3Dy > > +CONFIG_SYS_PROMPT=3D"nas440> " > > +# CONFIG_CMD_FLASH is not set > > +CONFIG_CMD_SATA=3Dy > > +CONFIG_CMD_PCI=3Dy > > +CONFIG_CMD_DM=3Dy > > +CONFIG_CMD_SCSI=3Dy > > +CONFIG_CMD_NAND=3Dy > > +CONFIG_CMD_USB=3Dy > > +# CONFIG_CMD_SETEXPR is not set > > +CONFIG_CMD_DHCP=3Dy > > +CONFIG_CMD_MII=3Dy > > +CONFIG_CMD_PING=3Dy > > +CONFIG_CMD_EXT2=3Dy > > +CONFIG_CMD_EXT4=3Dy > > +CONFIG_CMD_FAT=3Dy > > +CONFIG_CMD_JFFS2=3Dy > > +CONFIG_CMD_MTDPARTS=3Dy > > +CONFIG_MTDPARTS_DEFAULT=3D"mtdparts=3Dorion_nand:0xa0000@0x0(uboot),0x= 010000@0xa0000(env),0x500000@0xc0000(uimage),0x1a40000@0x5c0000(rootfs)" > > +CONFIG_CMD_UBI=3Dy > > +CONFIG_ISO_PARTITION=3Dy > > +CONFIG_EFI_PARTITION=3Dy > > +# CONFIG_PARTITION_UUIDS is not set > > +CONFIG_OF_CONTROL=3Dy > > +CONFIG_ENV_OVERWRITE=3Dy > > +CONFIG_ENV_IS_IN_NAND=3Dy > > +CONFIG_SYS_RELOC_GD_ENV_ADDR=3Dy > > +CONFIG_NETCONSOLE=3Dy > > +CONFIG_DM=3Dy > > +CONFIG_SYS_ATA_STRIDE=3D4 > > +CONFIG_SYS_ATA_DATA_OFFSET=3D0x100 > > +CONFIG_SYS_ATA_REG_OFFSET=3D0x100 > > +CONFIG_SYS_ATA_ALT_OFFSET=3D0x100 > > +CONFIG_KIRKWOOD_GPIO=3Dy > > +CONFIG_MVEBU_GPIO=3Dy > > +CONFIG_GPIO_EXTRA_HEADER=3Dy > > +CONFIG_DM_GPIO=3Dy > > +CONFIG_CMD_GPIO=3Dy > > +CONFIG_GPIO=3Dy > > +CONFIG_DM_GPIO_LOOKUP_LABEL=3Dy > > +# CONFIG_MMC is not set > > +CONFIG_MTD=3Dy > > +CONFIG_MTD_RAW_NAND=3Dy > > +CONFIG_PHY_MARVELL=3Dy > > +CONFIG_DM_ETH=3Dy > > +CONFIG_MVGBE=3Dy > > +CONFIG_MII=3Dy > > +CONFIG_SATA_MV=3Dy > > +CONFIG_SYS_SATA_MAX_DEVICE=3D2 > > +CONFIG_DM_RTC=3Dy > > +CONFIG_RTC_MV=3Dy > > +CONFIG_SYS_NS16550=3Dy > > +CONFIG_USB=3Dy > > +CONFIG_DM_USB=3Dy > > +CONFIG_USB_EHCI_HCD=3Dy > > +CONFIG_USB_STORAGE=3Dy > > + > > +CONFIG_PCI=3Dy > > +CONFIG_DM_PCI_COMPAT=3Dy > > +CONFIG_PCI_MVEBU=3Dy > > +CONFIG_AHCI_PCI=3Dy > > + > > +CONFIG_SCSI=3Dy > > +CONFIG_SCSI_AHCI=3Dy > > +CONFIG_DM_SCSI=3Dy > > diff --git a/drivers/ata/ahci-pci.c b/drivers/ata/ahci-pci.c > > index b1d231e0f9..af7e97dc4a 100644 > > --- a/drivers/ata/ahci-pci.c > > +++ b/drivers/ata/ahci-pci.c > > @@ -38,6 +38,7 @@ U_BOOT_DRIVER(ahci_pci) =3D { > > static struct pci_device_id ahci_pci_supported[] =3D { > > { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, ~0) }, > > { PCI_DEVICE(0x1b21, 0x0611) }, > > + { PCI_DEVICE(0x11ab, 0x6121) }, > > {}, > > }; > > > > diff --git a/include/configs/nas440.h b/include/configs/nas440.h > > new file mode 100644 > > index 0000000000..58e6afb2c3 > > --- /dev/null > > +++ b/include/configs/nas440.h > > @@ -0,0 +1,50 @@ > > +/* > > + * Copyright (C) 2022 Hajo Noerenberg > > + * > > + * based on work from: > > + * (C) Copyright 2009 > > + * Marvell Semiconductor > > + * Written-by: Prafulla Wadaskar > > + * > > + * SPDX-License-Identifier: GPL-2.0+ > > + */ > > + > > +#ifndef _CONFIG_NAS440_H > > +#define _CONFIG_NAS440_H > > + > > +/* > > + * mv-common.h should be defined after CMD configs since it used them > > + * to enable certain macros > > + */ > > + > > +#include "mv-common.h" > > + > > +/* > > + * Default environment variables > > + */ > > + > > +#define CONFIG_EXTRA_ENV_SETTINGS \ > > + "bootargs=3Dconsole=3DttyS0,115200\0" \ > > + "mtdids=3Dnand0=3Dorion_nand\0"\ > > + "mtdparts=3D" CONFIG_MTDPARTS_DEFAULT \ > > + "autostart=3Dno\0"\ > > + "autoload=3Dno\0" > > + > > +/* > > + * Ethernet Driver configuration > > + */ > > +#ifdef CONFIG_MVGBE > > +#define CONFIG_MVGBE_PORTS {1, 1} /* enable both ports */ > > +#define CONFIG_PHY_BASE_ADR 8 > > +#ifdef CONFIG_RESET_PHY_R > > +#undef CONFIG_RESET_PHY_R /* remove legacy reset_phy() */ > > +#endif > > +#endif /* CONFIG_MVGBE */ > > + > > +/* > > + * SATA driver configuration > > + */ > > +#define CONFIG_LBA48 > > +#define CONFIG_SYS_64BIT_LBA > > + > > +#endif /* _CONFIG_NAS440_H */ > > -- > > 2.20.1 > >