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 8D8BDC19F2D for ; Tue, 9 Aug 2022 11:32:36 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2A11B849EC; Tue, 9 Aug 2022 13:32:32 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=denx.de; s=phobos-20191101; t=1660044752; bh=9rxrdV7J4eC4FMtwT/SEDJPvdthZrPF5u/NgL6Mynhs=; h=Date:Subject:To:Cc:References:From:In-Reply-To:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=nnOR7mX2P2PAQ9Ev2/qTpxu4qSXH+tKbT+kJ4YLXwrORtMKziIVe8sv/EHvjbWVXX EiaPngIBTZuRXEneNMHbttSpPx/4Q32oRVFfH6TibZY50IDn8bIFBQ9QSpO3/2GCOP OmjgVSlu4fP7wtPtdxleBba91qqgRcGJao3UjFz3nBomEHVVNZaJuGGzr/Vo5OiJNj /rQO7JFuY6wbMXAw43JY7TuFsWAPyQAc+ODomLfdVSNfqqi1mtbcolbuKKHlpvVCDx qRgT87qZEjZ25hn1NwoQIRu4eU0lCRMqcm/bathstWZttFsiL7csXWHpCyAwqpjUhs yM34aiSnVjf+g== Received: by phobos.denx.de (Postfix, from userid 109) id 0C48B83FC0; Tue, 9 Aug 2022 13:32:24 +0200 (CEST) Received: from mout-u-204.mailbox.org (mout-u-204.mailbox.org [80.241.59.204]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id D63FE840A6 for ; Tue, 9 Aug 2022 13:32:18 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: phobos.denx.de; spf=fail smtp.mailfrom=sr@denx.de Received: from smtp1.mailbox.org (smtp1.mailbox.org [10.196.197.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-u-204.mailbox.org (Postfix) with ESMTPS id 4M29sF06Ldz9sQg; Tue, 9 Aug 2022 13:32:17 +0200 (CEST) Message-ID: <3e1b65f6-313c-d5c2-dc2b-cc21a3cddd97@denx.de> Date: Tue, 9 Aug 2022 13:32:15 +0200 MIME-Version: 1.0 Subject: Re: [PATCH 2/2] arm: mvebu: turris_omnia: Add support for design with SW reset signals Content-Language: en-US To: =?UTF-8?Q?Pali_Roh=c3=a1r?= , =?UTF-8?Q?Marek_Beh=c3=ban?= Cc: u-boot@lists.denx.de References: <20220729112907.8207-1-pali@kernel.org> <20220729112907.8207-2-pali@kernel.org> From: Stefan Roese In-Reply-To: <20220729112907.8207-2-pali@kernel.org> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit 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.6 at phobos.denx.de X-Virus-Status: Clean On 29.07.22 13:29, Pali Rohár wrote: > New Turris Omnia HW board revision requires that software controls > peripheral reset signals, namely PERST# signals on mPCIe slots, ethernet > phy reset and lan switch reset. Those pins are connected to MCU controlled > by MCU i2c API as GPIOs. On new HW board revision those pins stay in reset > after board reset and software has to release these peripherals from reset > manually. MCU announce this requirement by FEAT_PERIPH_MCU bit in > CMD_GET_FEATURES command. > > On older HW board revisions when FEAT_PERIPH_MCU is not announced, all > those reset signals are automatically released after board finish reset. > > Detect FEAT_PERIPH_MCU bit in board_fix_fdt() and ft_board_setup() > functions and insert into device tree blob pcie "reset-gpios" and eth phy > "phy-reset-gpios" properties with corresponding MCU gpio definitions. > PCIe and eth PHY drivers then automatically release resets during device > initialization. Both U-Boot and Linux kernel drivers support those device > tree reset properties. > > Initialization of lan switch on new HW board revision is more complicated. > Switch strapping pins are shared with switch RGMII pins. And strapping pins > must be in specific configuration after releasing switch reset. Due to pin > sharing, it is first required to switch A385 side of switch pins into GPIO > mode, set strapping configuration, release switch from reset and after that > switch A385 pins back to RGMII mode. > > Because this complicated setup is not supported by switch DSA drivers and > cannot be expressed easily in device tree, implement it manually in SPL > function spl_board_init(). So in proper U-Boot and OS/kernel would be lan > switch initialized and be in same configuration like it was on old HW board > revisions (where reset sequence did those steps at hardware level). > > Signed-off-by: Pali Rohár Applied to u-boot-marvell/master Thanks, Stefan > --- > board/CZ.NIC/turris_omnia/turris_omnia.c | 226 +++++++++++++++++++++++ > 1 file changed, 226 insertions(+) > > diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c > index 6fc2018c1cfb..e262ea1aba51 100644 > --- a/board/CZ.NIC/turris_omnia/turris_omnia.c > +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c > @@ -19,9 +19,11 @@ > #include > #include > #include > +#include > #include > #include > #include > +#include > #include > > #include "../drivers/ddr/marvell/a38x/ddr3_init.h" > @@ -65,6 +67,9 @@ enum mcu_commands { > > /* available if STS_FEATURES_SUPPORTED bit set in status word */ > CMD_GET_FEATURES = 0x10, > + > + /* available if EXT_CMD bit set in features */ > + CMD_EXT_CONTROL = 0x12, > }; > > enum status_word_bits { > @@ -81,6 +86,16 @@ enum status_word_bits { > /* CMD_GET_FEATURES */ > enum features_e { > FEAT_PERIPH_MCU = BIT(0), > + FEAT_EXT_CMDS = BIT(1), > +}; > + > +/* CMD_EXT_CONTROL */ > +enum ext_ctl_e { > + EXT_CTL_nRES_LAN = BIT(1), > + EXT_CTL_nRES_PHY = BIT(2), > + EXT_CTL_nPERST0 = BIT(3), > + EXT_CTL_nPERST1 = BIT(4), > + EXT_CTL_nPERST2 = BIT(5), > }; > > /* > @@ -543,6 +558,90 @@ static void handle_reset_button(void) > } > } > > +static void initialize_switch(void) > +{ > + u32 val, val04, val08, val10, val14; > + u16 ctrl[2]; > + int err; > + > + printf("Initializing LAN eth switch... "); > + > + /* Change RGMII pins to GPIO mode */ > + > + val = val04 = readl(MVEBU_MPP_BASE + 0x04); > + val &= ~GENMASK(19, 16); /* MPP[12] := GPIO */ > + val &= ~GENMASK(23, 20); /* MPP[13] := GPIO */ > + val &= ~GENMASK(27, 24); /* MPP[14] := GPIO */ > + val &= ~GENMASK(31, 28); /* MPP[15] := GPIO */ > + writel(val, MVEBU_MPP_BASE + 0x04); > + > + val = val08 = readl(MVEBU_MPP_BASE + 0x08); > + val &= ~GENMASK(3, 0); /* MPP[16] := GPIO */ > + val &= ~GENMASK(23, 20); /* MPP[21] := GPIO */ > + writel(val, MVEBU_MPP_BASE + 0x08); > + > + val = val10 = readl(MVEBU_MPP_BASE + 0x10); > + val &= ~GENMASK(27, 24); /* MPP[38] := GPIO */ > + val &= ~GENMASK(31, 28); /* MPP[39] := GPIO */ > + writel(val, MVEBU_MPP_BASE + 0x10); > + > + val = val14 = readl(MVEBU_MPP_BASE + 0x14); > + val &= ~GENMASK(3, 0); /* MPP[40] := GPIO */ > + val &= ~GENMASK(7, 4); /* MPP[41] := GPIO */ > + writel(val, MVEBU_MPP_BASE + 0x14); > + > + /* Set initial values for switch reset strapping pins */ > + > + val = readl(MVEBU_GPIO0_BASE + 0x00); > + val |= BIT(12); /* GPIO[12] := 1 */ > + val |= BIT(13); /* GPIO[13] := 1 */ > + val |= BIT(14); /* GPIO[14] := 1 */ > + val |= BIT(15); /* GPIO[15] := 1 */ > + val &= ~BIT(16); /* GPIO[16] := 0 */ > + val |= BIT(21); /* GPIO[21] := 1 */ > + writel(val, MVEBU_GPIO0_BASE + 0x00); > + > + val = readl(MVEBU_GPIO1_BASE + 0x00); > + val |= BIT(6); /* GPIO[38] := 1 */ > + val |= BIT(7); /* GPIO[39] := 1 */ > + val |= BIT(8); /* GPIO[40] := 1 */ > + val &= ~BIT(9); /* GPIO[41] := 0 */ > + writel(val, MVEBU_GPIO1_BASE + 0x00); > + > + val = readl(MVEBU_GPIO0_BASE + 0x04); > + val &= ~BIT(12); /* GPIO[12] := Out Enable */ > + val &= ~BIT(13); /* GPIO[13] := Out Enable */ > + val &= ~BIT(14); /* GPIO[14] := Out Enable */ > + val &= ~BIT(15); /* GPIO[15] := Out Enable */ > + val &= ~BIT(16); /* GPIO[16] := Out Enable */ > + val &= ~BIT(21); /* GPIO[21] := Out Enable */ > + writel(val, MVEBU_GPIO0_BASE + 0x04); > + > + val = readl(MVEBU_GPIO1_BASE + 0x04); > + val &= ~BIT(6); /* GPIO[38] := Out Enable */ > + val &= ~BIT(7); /* GPIO[39] := Out Enable */ > + val &= ~BIT(8); /* GPIO[40] := Out Enable */ > + val &= ~BIT(9); /* GPIO[41] := Out Enable */ > + writel(val, MVEBU_GPIO1_BASE + 0x04); > + > + /* Release switch reset */ > + > + ctrl[0] = EXT_CTL_nRES_LAN; > + ctrl[1] = EXT_CTL_nRES_LAN; > + err = omnia_mcu_write(CMD_EXT_CONTROL, ctrl, sizeof(ctrl)); > + > + mdelay(10); > + > + /* Change RGMII pins back to RGMII mode */ > + > + writel(val04, MVEBU_MPP_BASE + 0x04); > + writel(val08, MVEBU_MPP_BASE + 0x08); > + writel(val10, MVEBU_MPP_BASE + 0x10); > + writel(val14, MVEBU_MPP_BASE + 0x14); > + > + puts(err ? "failed\n" : "done\n"); > +} > + > int board_early_init_f(void) > { > /* Configure MPP */ > @@ -572,6 +671,9 @@ int board_early_init_f(void) > > void spl_board_init(void) > { > + u16 val; > + int ret; > + > /* > * If booting from UART, disable MCU watchdog in SPL, since uploading > * U-Boot proper can take too much time and trigger it. Instead enable > @@ -581,6 +683,19 @@ void spl_board_init(void) > enable_a385_watchdog(10); > disable_mcu_watchdog(); > } > + > + /* > + * When MCU controls peripheral resets then release LAN eth switch from > + * the reset and initialize it. When MCU does not control peripheral > + * resets then LAN eth switch is initialized automatically by bootstrap > + * pins when A385 is released from the reset. > + */ > + ret = omnia_mcu_read(CMD_GET_STATUS_WORD, &val, sizeof(val)); > + if (ret == 0 && (val & STS_FEATURES_SUPPORTED)) { > + ret = omnia_mcu_read(CMD_GET_FEATURES, &val, sizeof(val)); > + if (ret == 0 && (val & FEAT_PERIPH_MCU)) > + initialize_switch(); > + } > } > > #if IS_ENABLED(CONFIG_OF_BOARD_FIXUP) || IS_ENABLED(CONFIG_OF_BOARD_SETUP) > @@ -689,11 +804,109 @@ static void fixup_wwan_port_nodes(void *blob) > disable_pcie_node(blob, 2); > } > > +static int insert_mcu_gpio_prop(void *blob, int node, const char *prop, > + unsigned int phandle, u32 bank, u32 gpio, > + u32 flags) > +{ > + fdt32_t val[4] = { cpu_to_fdt32(phandle), cpu_to_fdt32(bank), > + cpu_to_fdt32(gpio), cpu_to_fdt32(flags) }; > + return fdt_setprop(blob, node, prop, &val, sizeof(val)); > +} > + > +static int fixup_mcu_gpio_in_pcie_nodes(void *blob) > +{ > + unsigned int mcu_phandle; > + int port, gpio; > + int pcie_node; > + int port_node; > + int ret; > + > + ret = fdt_increase_size(blob, 128); > + if (ret < 0) { > + printf("Cannot increase FDT size!\n"); > + return ret; > + } > + > + mcu_phandle = fdt_create_phandle_by_compatible(blob, "cznic,turris-omnia-mcu"); > + if (!mcu_phandle) > + return -FDT_ERR_NOPHANDLES; > + > + fdt_for_each_node_by_compatible(pcie_node, blob, -1, "marvell,armada-370-pcie") { > + if (!fdtdec_get_is_enabled(blob, pcie_node)) > + continue; > + > + fdt_for_each_subnode(port_node, blob, pcie_node) { > + if (!fdtdec_get_is_enabled(blob, port_node)) > + continue; > + > + port = fdtdec_get_int(blob, port_node, "marvell,pcie-port", -1); > + > + if (port == 0) > + gpio = ilog2(EXT_CTL_nPERST0); > + else if (port == 1) > + gpio = ilog2(EXT_CTL_nPERST1); > + else if (port == 2) > + gpio = ilog2(EXT_CTL_nPERST2); > + else > + continue; > + > + /* insert: reset-gpios = <&mcu 2 gpio GPIO_ACTIVE_LOW>; */ > + ret = insert_mcu_gpio_prop(blob, port_node, "reset-gpios", > + mcu_phandle, 2, gpio, GPIO_ACTIVE_LOW); > + if (ret < 0) > + return ret; > + } > + } > + > + return 0; > +} > + > +static int fixup_mcu_gpio_in_eth_wan_node(void *blob) > +{ > + unsigned int mcu_phandle; > + int eth_wan_node; > + int ret; > + > + ret = fdt_increase_size(blob, 64); > + if (ret < 0) { > + printf("Cannot increase FDT size!\n"); > + return ret; > + } > + > + eth_wan_node = fdt_path_offset(blob, "ethernet2"); > + if (eth_wan_node < 0) > + return eth_wan_node; > + > + mcu_phandle = fdt_create_phandle_by_compatible(blob, "cznic,turris-omnia-mcu"); > + if (!mcu_phandle) > + return -FDT_ERR_NOPHANDLES; > + > + /* insert: phy-reset-gpios = <&mcu 2 gpio GPIO_ACTIVE_LOW>; */ > + ret = insert_mcu_gpio_prop(blob, eth_wan_node, "phy-reset-gpios", > + mcu_phandle, 2, ilog2(EXT_CTL_nRES_PHY), GPIO_ACTIVE_LOW); > + if (ret < 0) > + return ret; > + > + return 0; > +} > + > #endif > > #if IS_ENABLED(CONFIG_OF_BOARD_FIXUP) > int board_fix_fdt(void *blob) > { > + u16 val; > + int ret; > + > + ret = omnia_mcu_read(CMD_GET_STATUS_WORD, &val, sizeof(val)); > + if (ret == 0 && (val & STS_FEATURES_SUPPORTED)) { > + ret = omnia_mcu_read(CMD_GET_FEATURES, &val, sizeof(val)); > + if (ret == 0 && (val & FEAT_PERIPH_MCU)) { > + fixup_mcu_gpio_in_pcie_nodes(blob); > + fixup_mcu_gpio_in_eth_wan_node(blob); > + } > + } > + > fixup_msata_port_nodes(blob); > fixup_wwan_port_nodes(blob); > > @@ -840,6 +1053,19 @@ fail: > > int ft_board_setup(void *blob, struct bd_info *bd) > { > + int node; > + > + /* > + * U-Boot's FDT blob contains phy-reset-gpios in ethernet2 > + * node when MCU controls all peripherals resets. > + * Fixup MCU GPIO nodes in PCIe and eth wan nodes in this case. > + */ > + node = fdt_path_offset(gd->fdt_blob, "ethernet2"); > + if (node >= 0 && fdt_getprop(gd->fdt_blob, node, "phy-reset-gpios", NULL)) { > + fixup_mcu_gpio_in_pcie_nodes(blob); > + fixup_mcu_gpio_in_eth_wan_node(blob); > + } > + > fixup_spi_nor_partitions(blob); > fixup_msata_port_nodes(blob); > fixup_wwan_port_nodes(blob); Viele Grüße, Stefan Roese -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr@denx.de