U-Boot
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
May 2021
- 191 participants
- 563 discussions

05 May '21
All newer Allwinner SoCs (since about 2013) miss the CONFIGDATA register
in their MUSB implementation, so they need a quirk to hardcode this.
Currently this quirk depends on listing the SoCs affected in musb_reg.h,
which means that this list needs to grow with every new chip.
Move the quirk feature into Kconfig, next to PIO_ONLY, and change the
default to y (for Allwinner builds), while listing the early
implementations as exceptions.
This fixes USB peripheral operation on some newer SoCs, which were not
explicitly listed before.
Tested on H6, H616, R40 (which were broken before), and also on the H5
and A20, for regressions.
Signed-off-by: Andre Przywara <andre.przywara(a)arm.com>
---
Hi,
a bit more elaborate than the first version, but hopefully cleaner and
more robust this time: we should never need to add anything to get new
SoCs covered.
Cheers,
Andre
Changelog v1 .. v2:
- Add Kconfig variable
- Switch to listing the exceptions instead of all affected SoCs
drivers/usb/musb-new/Kconfig | 10 ++++++++++
drivers/usb/musb-new/musb_regs.h | 3 +--
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig
index 6cf8a2b60b6..fd6f4109b0e 100644
--- a/drivers/usb/musb-new/Kconfig
+++ b/drivers/usb/musb-new/Kconfig
@@ -89,3 +89,13 @@ config USB_MUSB_PIO_ONLY
help
All data is copied between memory and FIFO by the CPU.
DMA controllers are ignored.
+
+config USB_MUSB_FIXED_CONFIGDATA
+ bool "Hardcode MUSB CONFIGDATA register"
+ depends on USB_MUSB_SUNXI
+ default n if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || MACH_SUN7I || MACH_SUN8I_A23
+ default y
+ help
+ Newer Allwinner SoCs do not implement the MUSB_CONFIGDATA register,
+ so it always reads 0. Select this option to override this and
+ return a hardcoded value instead.
diff --git a/drivers/usb/musb-new/musb_regs.h b/drivers/usb/musb-new/musb_regs.h
index c4d7203b851..e9362f6def3 100644
--- a/drivers/usb/musb-new/musb_regs.h
+++ b/drivers/usb/musb-new/musb_regs.h
@@ -431,8 +431,7 @@ static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase)
static inline u8 musb_read_configdata(void __iomem *mbase)
{
-#if defined CONFIG_MACH_SUN8I_A33 || defined CONFIG_MACH_SUN8I_A83T || \
- defined CONFIG_MACH_SUNXI_H3_H5 || defined CONFIG_MACH_SUN50I
+#ifdef CONFIG_USB_MUSB_FIXED_CONFIGDATA
/* <Sigh> allwinner saves a reg, and we need to hardcode this */
return 0xde;
#else
--
2.17.5
2
1
The H616 is our first supported Allwinner SoC which goes beyond the 4GB
address space "barrier", by having more than 32 address bits.
Lift the preliminary 3GB DRAM limit for the H616, and update the page
table setup on the way, to actually map that last GB as well.
As not all devices are actually capable of dealing with more than 32
bits (the DMA in the EMAC for instance), we also limit U-Boot's own
DRAM usage to 4GB on the way.
Signed-off-by: Andre Przywara <andre.przywara(a)arm.com>
---
Changelog v1 .. v2:
- limit ram_top to 4GB to fix Ethernet DMA
arch/arm/mach-sunxi/Kconfig | 4 ++--
arch/arm/mach-sunxi/board.c | 11 ++++++++++-
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 8e9012dbbfe..f052557da4c 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -190,10 +190,10 @@ config MACH_SUNXI_H3_H5
select SUPPORT_SPL
# TODO: try out A80's 8GiB DRAM space
-# TODO: H616 supports 4 GiB DRAM space
config SUNXI_DRAM_MAX_SIZE
hex
- default 0xC0000000 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6 || MACH_SUN50I_H616
+ default 0x100000000 if MACH_SUN50I_H616
+ default 0xC0000000 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6
default 0x80000000
choice
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 503538e26d3..2de3ab2b4ef 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -56,7 +56,7 @@ static struct mm_region sunxi_mem_map[] = {
/* RAM */
.virt = 0x40000000UL,
.phys = 0x40000000UL,
- .size = 0xC0000000UL,
+ .size = CONFIG_SUNXI_DRAM_MAX_SIZE,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
@@ -65,6 +65,15 @@ static struct mm_region sunxi_mem_map[] = {
}
};
struct mm_region *mem_map = sunxi_mem_map;
+
+ulong board_get_usable_ram_top(ulong total_size)
+{
+ /* Some devices (like the EMAC) have a 32-bit DMA limit. */
+ if (gd->ram_top > (1ULL << 32))
+ return 1ULL << 32;
+
+ return gd->ram_top;
+}
#endif
static int gpio_init(void)
--
2.17.5
1
0
Board designed for quick prototyping and has one microSD port,
2 Ethernet ports, 2 USB ports, I2C, SPI, CAN, RS-485, GPIO,
UART interfaces, and 2 RGB LEDs.
Signed-off-by: Oleh Kravchenko <oleg(a)kaa.org.ua>
---
MAINTAINERS | 10 +
arch/arm/dts/Makefile | 3 +
arch/arm/dts/o4-imx-nano.dts | 241 ++++++++++++++++++
arch/arm/dts/o4-imx6ull-nano.dtsi | 87 +++++++
arch/arm/mach-imx/mx6/Kconfig | 13 +
.../out4/o4-imx6ull-nano/K4B4G1646D-BCMA.cfg | 91 +++++++
board/out4/o4-imx6ull-nano/Kconfig | 57 +++++
.../o4-imx6ull-nano/MT41K256M16HA-125E.cfg | 91 +++++++
board/out4/o4-imx6ull-nano/Makefile | 4 +
board/out4/o4-imx6ull-nano/o4-imx6ull-nano.c | 81 ++++++
configs/o4-imx6ull-nano_defconfig | 103 ++++++++
include/configs/o4-imx6ull-nano.h | 25 ++
12 files changed, 806 insertions(+)
create mode 100644 arch/arm/dts/o4-imx-nano.dts
create mode 100644 arch/arm/dts/o4-imx6ull-nano.dtsi
create mode 100644 board/out4/o4-imx6ull-nano/K4B4G1646D-BCMA.cfg
create mode 100644 board/out4/o4-imx6ull-nano/Kconfig
create mode 100644 board/out4/o4-imx6ull-nano/MT41K256M16HA-125E.cfg
create mode 100644 board/out4/o4-imx6ull-nano/Makefile
create mode 100644 board/out4/o4-imx6ull-nano/o4-imx6ull-nano.c
create mode 100644 configs/o4-imx6ull-nano_defconfig
create mode 100644 include/configs/o4-imx6ull-nano.h
diff --git a/MAINTAINERS b/MAINTAINERS
index c6dd9bf838..786476c016 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -916,6 +916,16 @@ S: Orphaned (Since 2017-01)
T: git https://source.denx.de/u-boot/custodians/u-boot-onenand.git
F: drivers/mtd/onenand/
+OUT4-IMX6ULL-NANO BOARD
+M: Oleh Kravchenko <oleg(a)kaa.org.ua>
+S: Maintained
+T: git https://github.com/Oleh-Kravchenko/u-boot-out4.git
+F: arch/arm/dts/o4-imx-nano.dts
+F: arch/arm/dts/o4-imx6ull-nano.dtsi
+F: board/out4
+F: configs/o4-imx6ull-nano_defconfig
+F: include/configs/o4-imx6ull-nano.h
+
PATMAN
M: Simon Glass <sjg(a)chromium.org>
S: Maintained
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 9a8de46272..0b2de37280 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -764,6 +764,9 @@ dtb-$(CONFIG_ARCH_MX6) += \
imx6-apalis.dtb \
imx6-colibri.dtb
+dtb-$(CONFIG_O4_IMX_NANO) += \
+ o4-imx-nano.dtb
+
dtb-$(CONFIG_MX7) += imx7d-sdb.dtb \
imx7d-sdb-qspi.dtb \
imx7-colibri-emmc.dtb \
diff --git a/arch/arm/dts/o4-imx-nano.dts b/arch/arm/dts/o4-imx-nano.dts
new file mode 100644
index 0000000000..d1785b7dc7
--- /dev/null
+++ b/arch/arm/dts/o4-imx-nano.dts
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (C) 2021 Oleh Kravchenko <oleg(a)kaa.org.ua>
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+
+#include "o4-imx6ull-nano.dtsi"
+
+/ {
+ model = "O4-iMX-NANO";
+ compatible = "out4,o4-imx-nano",
+ "out4,o4-imx6ull-nano",
+ "fsl,imx6ull";
+
+ aliases {
+ mmc1 = &usdhc1;
+ };
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led@0 {
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&pcf8574a 0 GPIO_ACTIVE_LOW>;
+ reg = <0>;
+ };
+
+ led@1 {
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&pcf8574a 1 GPIO_ACTIVE_LOW>;
+ reg = <1>;
+ };
+
+ led@2 {
+ gpios = <&pcf8574a 2 GPIO_ACTIVE_LOW>;
+ color = <LED_COLOR_ID_BLUE>;
+ reg = <2>;
+ };
+
+ led@3 {
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&pcf8574a 3 GPIO_ACTIVE_LOW>;
+ reg = <3>;
+ };
+
+ led@4 {
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&pcf8574a 4 GPIO_ACTIVE_LOW>;
+ reg = <4>;
+ };
+
+ led@5 {
+ color = <LED_COLOR_ID_BLUE>;
+ gpios = <&pcf8574a 5 GPIO_ACTIVE_LOW>;
+ reg = <5>;
+ };
+ };
+
+ usbotg1_vbus: reg_usbotg1_vbus {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&pcf8574a 6 GPIO_ACTIVE_HIGH>;
+ regulator-max-microvolt = <5000000>;
+ regulator-min-microvolt = <5000000>;
+ regulator-name = "usb0";
+ };
+
+ usbotg2_vbus: reg_usbotg2_vbus {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&pcf8574a 7 GPIO_ACTIVE_HIGH>;
+ regulator-max-microvolt = <5000000>;
+ regulator-min-microvolt = <5000000>;
+ regulator-name = "usb1";
+ };
+};
+
+&iomuxc {
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
+ MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10069
+ MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059
+ MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
+ MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
+ MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
+ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
+ MX6UL_PAD_UART1_RTS_B__USDHC1_CD_B 0x03029
+ >;
+ };
+
+ pinctrl_mdio: mdiogrp {
+ fsl,pins = <
+ MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
+ MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0
+ MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0xb0b0 /* RST */
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_HSYNC__I2C2_SCL 0x4001b8b0
+ MX6UL_PAD_CSI_VSYNC__I2C2_SDA 0x4001b8b0
+ >;
+ };
+
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX6UL_PAD_CSI_HSYNC__GPIO4_IO20 0x1b8b0
+ MX6UL_PAD_CSI_VSYNC__GPIO4_IO19 0x1b8b0
+ >;
+ };
+
+ pinctrl_can1: can1grp {
+ fsl,pins = <
+ MX6UL_PAD_LCD_DATA08__FLEXCAN1_TX 0x1b020
+ MX6UL_PAD_LCD_DATA09__FLEXCAN1_RX 0x1b020
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1
+ MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1
+ MX6UL_PAD_UART2_CTS_B__UART2_DCE_CTS 0x1b0b1
+ >;
+ };
+};
+
+&uart1 {
+ pinctrl-0 = <&pinctrl_uart1>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&usdhc1 {
+ bus-width = <4>;
+ no-1-8-v;
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-names = "default";
+ status = "okay";
+ wakeup-source;
+};
+
+&fec1 {
+ phy-handle = <&phy0>;
+ phy-mode = "rmii";
+ pinctrl-0 = <&pinctrl_fec1>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&fec2 {
+ phy-handle = <&phy1>;
+ phy-mode = "rmii";
+ phy-reset-duration = <250>;
+ phy-reset-post-delay = <100>;
+ phy-reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&pinctrl_fec2 &pinctrl_mdio>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy0: ethernet-phy@0 {
+ clocks = <&clks IMX6UL_CLK_ENET_REF>;
+ clock-names = "rmii-ref";
+ interrupt-parent = <&gpio5>;
+ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-0 = <&pinctrl_phy0_irq>;
+ pinctrl-names = "default";
+ reg = <0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ clocks = <&clks IMX6UL_CLK_ENET2_REF>;
+ clock-names = "rmii-ref";
+ interrupt-parent = <&gpio5>;
+ interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-0 = <&pinctrl_phy1_irq>;
+ pinctrl-names = "default";
+ reg = <1>;
+ };
+ };
+};
+
+&usbotg1 {
+ dr_mode = "host";
+ status = "okay";
+ vbus-supply = <&usbotg1_vbus>;
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ status = "okay";
+ vbus-supply = <&usbotg2_vbus>;
+};
+
+&i2c2 {
+ clock_frequency = <100000>;
+ pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ pinctrl-names = "default", "gpio";
+ scl-gpios = <&gpio4 20 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio4 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+
+ pcf8574a: gpio@38 {
+ compatible = "nxp,pcf8574a";
+ #gpio-cells = <2>;
+ gpio-controller;
+ reg = <0x38>;
+ };
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can1>;
+ status = "okay";
+};
+
+&uart2 {
+ linux,rs485-enabled-at-boot-time;
+ pinctrl-0 = <&pinctrl_uart2>;
+ pinctrl-names = "default";
+ status = "okay";
+ uart-has-rtscts;
+};
diff --git a/arch/arm/dts/o4-imx6ull-nano.dtsi b/arch/arm/dts/o4-imx6ull-nano.dtsi
new file mode 100644
index 0000000000..3fefa80eae
--- /dev/null
+++ b/arch/arm/dts/o4-imx6ull-nano.dtsi
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (C) 2021 Oleh Kravchenko <oleg(a)kaa.org.ua>
+
+/dts-v1/;
+
+#include "imx6ull.dtsi"
+
+/ {
+ model = "O4-iMX6ULL-NANO";
+ compatible = "out4,o4-imx6ull-nano", "fsl,imx6ull";
+
+ aliases {
+ mmc0 = &usdhc2;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x20000000>;
+ };
+};
+
+&iomuxc {
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_ALE__USDHC2_RESET_B 0x17059
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
+ MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059
+ MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059
+ MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059
+ MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10069
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
+ >;
+ };
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031
+ MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0
+ >;
+ };
+
+ pinctrl_fec2: fec2grp {
+ fsl,pins = <
+ MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
+ MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
+ MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031
+ MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
+ MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
+ MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
+ >;
+ };
+
+ pinctrl_phy0_irq: phy0grp {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x79
+ >;
+ };
+
+ pinctrl_phy1_irq: phy1grp {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x79
+ >;
+ };
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ no-1-8-v;
+ non-removable;
+ keep-power-in-suspend;
+ wakeup-source;
+ bus-width = <8>;
+ status = "okay";
+};
diff --git a/arch/arm/mach-imx/mx6/Kconfig b/arch/arm/mach-imx/mx6/Kconfig
index 92fb4c4f23..419ae79cd0 100644
--- a/arch/arm/mach-imx/mx6/Kconfig
+++ b/arch/arm/mach-imx/mx6/Kconfig
@@ -688,6 +688,18 @@ config TARGET_BRPPT2
Support
B&R BRPPT2 platform
based on Freescale's iMX6 SoC
+
+config TARGET_O4_IMX6ULL_NANO
+ bool "O4-iMX6ULL-NANO"
+ depends on MX6ULL
+ select BOARD_LATE_INIT
+ select DM
+ select DM_THERMAL
+ imply CMD_DM
+ help
+ Support for www.out4.ru O4-iMX6UL-NANO platform
+ based on Freescale's i.MX6UL/i.MX6ULL SoC.
+
endchoice
config SYS_SOC
@@ -747,5 +759,6 @@ source "board/udoo/neo/Kconfig"
source "board/wandboard/Kconfig"
source "board/warp/Kconfig"
source "board/BuR/brppt2/Kconfig"
+source "board/out4/o4-imx6ull-nano/Kconfig"
endif
diff --git a/board/out4/o4-imx6ull-nano/K4B4G1646D-BCMA.cfg b/board/out4/o4-imx6ull-nano/K4B4G1646D-BCMA.cfg
new file mode 100644
index 0000000000..c0dcfe9a0c
--- /dev/null
+++ b/board/out4/o4-imx6ull-nano/K4B4G1646D-BCMA.cfg
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (C) 2016 Freescale Semiconductor, Inc.
+// Copyright (C) 2021 Oleh Kravchenko <oleg(a)kaa.org.ua>
+
+#define __ASSEMBLY__
+#include <config.h>
+
+/* image version */
+
+IMAGE_VERSION 2
+BOOT_FROM sd
+
+#ifdef CONFIG_IMX_HAB
+CSF CONFIG_CSF_SIZE
+#endif
+
+/*
+ * Device Configuration Data (DCD)
+ *
+ * Each entry must have the format:
+ * Addr-type Address Value
+ *
+ * where:
+ * Addr-type register length (1,2 or 4 bytes)
+ * Address absolute address of the register
+ * value value to be stored in the register
+ */
+
+/* Enable all clocks */
+DATA 4 0x020c4068 0xffffffff
+DATA 4 0x020c406c 0xffffffff
+DATA 4 0x020c4070 0xffffffff
+DATA 4 0x020c4074 0xffffffff
+DATA 4 0x020c4078 0xffffffff
+DATA 4 0x020c407c 0xffffffff
+DATA 4 0x020c4080 0xffffffff
+
+/* Samsung K4B4G1646D-BCMA */
+DATA 4 0x020e04b4 0x000c0000
+DATA 4 0x020e04ac 0x00000000
+DATA 4 0x020e027c 0x00000030
+DATA 4 0x020e0250 0x00000030
+DATA 4 0x020e024c 0x00000030
+DATA 4 0x020e0490 0x00000030
+DATA 4 0x020e0288 0x000c0030
+DATA 4 0x020e0270 0x00000000
+DATA 4 0x020e0260 0x00000030
+DATA 4 0x020e0264 0x00000030
+DATA 4 0x020e04a0 0x00000030
+DATA 4 0x020e0494 0x00020000
+DATA 4 0x020e0280 0x00000030
+DATA 4 0x020e0284 0x00000030
+DATA 4 0x020e04b0 0x00020000
+DATA 4 0x020e0498 0x00000030
+DATA 4 0x020e04a4 0x00000030
+DATA 4 0x020e0244 0x00000030
+DATA 4 0x020e0248 0x00000030
+DATA 4 0x021b001c 0x00008000
+DATA 4 0x021b0800 0xa1390003
+DATA 4 0x021b080c 0x00030009
+DATA 4 0x021b083c 0x01440148
+DATA 4 0x021b0848 0x40403640
+DATA 4 0x021b0850 0x4040322a
+DATA 4 0x021b081c 0x33333333
+DATA 4 0x021b0820 0x33333333
+DATA 4 0x021b082c 0xf3333333
+DATA 4 0x021b0830 0xf3333333
+DATA 4 0x021b08c0 0x00944009
+DATA 4 0x021b08b8 0x00000800
+DATA 4 0x021b0004 0x0002002d
+DATA 4 0x021b0008 0x1b333030
+DATA 4 0x021b000c 0x676b52f2
+DATA 4 0x021b0010 0x926d0b63
+DATA 4 0x021b0014 0x01ff00db
+DATA 4 0x021b0018 0x00211740
+DATA 4 0x021b001c 0x00008000
+DATA 4 0x021b002c 0x000026d2
+DATA 4 0x021b0030 0x006b1023
+DATA 4 0x021b0040 0x0000004f
+DATA 4 0x021b0000 0x84180000
+DATA 4 0x021b0890 0x00400000
+DATA 4 0x021b001c 0x02008032
+DATA 4 0x021b001c 0x00008033
+DATA 4 0x021b001c 0x00048031
+DATA 4 0x021b001c 0x15108030
+DATA 4 0x021b001c 0x04008040
+DATA 4 0x021b0020 0x00007800
+DATA 4 0x021b0818 0x00000227
+DATA 4 0x021b0004 0x0002552d
+DATA 4 0x021b0404 0x00011006
+DATA 4 0x021b001c 0x00000000
diff --git a/board/out4/o4-imx6ull-nano/Kconfig b/board/out4/o4-imx6ull-nano/Kconfig
new file mode 100644
index 0000000000..c2497d521f
--- /dev/null
+++ b/board/out4/o4-imx6ull-nano/Kconfig
@@ -0,0 +1,57 @@
+if TARGET_O4_IMX6ULL_NANO
+
+config SYS_BOARD
+ default "o4-imx6ull-nano"
+
+config SYS_VENDOR
+ default "out4"
+
+config SYS_CONFIG_NAME
+ default "o4-imx6ull-nano"
+
+choice
+ prompt "Memory model"
+ default K4B4G1646D_BCMA
+ help
+ Memory type setup.
+
+ Please choose correct memory model here.
+
+config K4B4G1646D_BCMA
+ bool "K4B4G1646D-BCMA 256Mx16 (512 MiB/chip)"
+ help
+ Samsung DDR3 SDRAM
+ K4B4G1646D-BCMA
+
+config MT41K256M16HA_125E
+ bool "MT41K256M16HA-125:E 256Mx16 (512 MiB/chip)"
+ help
+ Micron DDR3L SDRAM
+ MT41K256M16HA-125:E
+
+endchoice
+
+choice
+ prompt "Mainboard model"
+ default O4_IMX_NANO
+ help
+ Mainboard setup.
+
+ Please choose correct main board model here.
+
+config O4_IMX_NANO
+ bool "O4-iMX-NANO"
+ help
+ A baseboard for EV-iMX280-NANO module:
+ https://out4.ru/products/board/18-o4-imx-nano.html
+
+endchoice
+
+config IMX_CONFIG
+ default "board/out4/o4-imx6ull-nano/K4B4G1646D-BCMA.cfg" if K4B4G1646D_BCMA
+ default "board/out4/o4-imx6ull-nano/MT41K256M16HA-125E.cfg" if MT41K256M16HA_125E
+
+config DEFAULT_DEVICE_TREE
+ default "o4-imx-nano" if O4_IMX_NANO
+
+endif
diff --git a/board/out4/o4-imx6ull-nano/MT41K256M16HA-125E.cfg b/board/out4/o4-imx6ull-nano/MT41K256M16HA-125E.cfg
new file mode 100644
index 0000000000..6f823a7272
--- /dev/null
+++ b/board/out4/o4-imx6ull-nano/MT41K256M16HA-125E.cfg
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (C) 2016 Freescale Semiconductor, Inc.
+// Copyright (C) 2021 Oleh Kravchenko <oleg(a)kaa.org.ua>
+
+#define __ASSEMBLY__
+#include <config.h>
+
+/* image version */
+
+IMAGE_VERSION 2
+BOOT_FROM sd
+
+#ifdef CONFIG_IMX_HAB
+CSF CONFIG_CSF_SIZE
+#endif
+
+/*
+ * Device Configuration Data (DCD)
+ *
+ * Each entry must have the format:
+ * Addr-type Address Value
+ *
+ * where:
+ * Addr-type register length (1,2 or 4 bytes)
+ * Address absolute address of the register
+ * value value to be stored in the register
+ */
+
+/* Enable all clocks */
+DATA 4 0x020c4068 0xffffffff
+DATA 4 0x020c406c 0xffffffff
+DATA 4 0x020c4070 0xffffffff
+DATA 4 0x020c4074 0xffffffff
+DATA 4 0x020c4078 0xffffffff
+DATA 4 0x020c407c 0xffffffff
+DATA 4 0x020c4080 0xffffffff
+
+/* Micron MT41K256M16HA-125:E */
+DATA 4 0x020e04b4 0x000c0000
+DATA 4 0x020e04ac 0x00000000
+DATA 4 0x020e027c 0x00000030
+DATA 4 0x020e0250 0x00000030
+DATA 4 0x020e024c 0x00000030
+DATA 4 0x020e0490 0x00000030
+DATA 4 0x020e0288 0x000c0030
+DATA 4 0x020e0270 0x00000000
+DATA 4 0x020e0260 0x00000030
+DATA 4 0x020e0264 0x00000030
+DATA 4 0x020e04a0 0x00000030
+DATA 4 0x020e0494 0x00020000
+DATA 4 0x020e0280 0x00000030
+DATA 4 0x020e0284 0x00000030
+DATA 4 0x020e04b0 0x00020000
+DATA 4 0x020e0498 0x00000030
+DATA 4 0x020e04a4 0x00000030
+DATA 4 0x020e0244 0x00000030
+DATA 4 0x020e0248 0x00000030
+DATA 4 0x021b001c 0x00008000
+DATA 4 0x021b0800 0xa1390003
+DATA 4 0x021b080c 0x0005000b
+DATA 4 0x021b083c 0x01400144
+DATA 4 0x021b0848 0x4040343a
+DATA 4 0x021b0850 0x4040342a
+DATA 4 0x021b081c 0x33333333
+DATA 4 0x021b0820 0x33333333
+DATA 4 0x021b082c 0xf3333333
+DATA 4 0x021b0830 0xf3333333
+DATA 4 0x021b08c0 0x00944009
+DATA 4 0x021b08b8 0x00000800
+DATA 4 0x021b0004 0x0002002d
+DATA 4 0x021b0008 0x1b333030
+DATA 4 0x021b000c 0x676b52f2
+DATA 4 0x021b0010 0x91eb0b63
+DATA 4 0x021b0014 0x01ff00db
+DATA 4 0x021b0018 0x00211740
+DATA 4 0x021b001c 0x00008000
+DATA 4 0x021b002c 0x000026d2
+DATA 4 0x021b0030 0x006b1023
+DATA 4 0x021b0040 0x0000004f
+DATA 4 0x021b0000 0x84180000
+DATA 4 0x021b0890 0x00400000
+DATA 4 0x021b001c 0x02008032
+DATA 4 0x021b001c 0x00008033
+DATA 4 0x021b001c 0x00048031
+DATA 4 0x021b001c 0x15108030
+DATA 4 0x021b001c 0x04008040
+DATA 4 0x021b0020 0x00007800
+DATA 4 0x021b0818 0x00000227
+DATA 4 0x021b0004 0x0002552d
+DATA 4 0x021b0404 0x00011006
+DATA 4 0x021b001c 0x00000000
diff --git a/board/out4/o4-imx6ull-nano/Makefile b/board/out4/o4-imx6ull-nano/Makefile
new file mode 100644
index 0000000000..a3f4646d9e
--- /dev/null
+++ b/board/out4/o4-imx6ull-nano/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2021 Oleh Kravchenko <oleg(a)kaa.org.ua>
+
+obj-y := o4-imx6ull-nano.o
diff --git a/board/out4/o4-imx6ull-nano/o4-imx6ull-nano.c b/board/out4/o4-imx6ull-nano/o4-imx6ull-nano.c
new file mode 100644
index 0000000000..eb71e4c08c
--- /dev/null
+++ b/board/out4/o4-imx6ull-nano/o4-imx6ull-nano.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (C) 2021 Oleh Kravchenko <oleg(a)kaa.org.ua>
+
+#include <asm/arch-mx6/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/global_data.h>
+#include <asm/mach-imx/boot_mode.h>
+#include <common.h>
+#include <env.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+ gd->ram_size = imx_ddr_size();
+
+ return 0;
+}
+
+int board_early_init_f(void)
+{
+ return 0;
+}
+
+static int setup_fec_clock(void)
+{
+ if (IS_ENABLED(CONFIG_FEC_MXC) && !IS_ENABLED(CONFIG_CLK_IMX6Q)) {
+ struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
+ int ret;
+
+ /*
+ * Use 50M anatop loopback REF_CLK1 for ENET1,
+ * clear gpr1[13], set gpr1[17].
+ */
+ clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC1_MASK,
+ IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK);
+
+ ret = enable_fec_anatop_clock(0, ENET_50MHZ);
+ if (ret)
+ return ret;
+
+ /*
+ * Use 50M anatop loopback REF_CLK2 for ENET2,
+ * clear gpr1[14], set gpr1[18].
+ */
+ clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC2_MASK,
+ IOMUX_GPR1_FEC2_CLOCK_MUX1_SEL_MASK);
+
+ ret = enable_fec_anatop_clock(1, ENET_50MHZ);
+ if (ret)
+ return ret;
+
+ enable_enet_clk(1);
+ }
+
+ return 0;
+}
+
+int board_init(void)
+{
+ /* Address of boot parameters */
+ gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+ return setup_fec_clock();
+}
+
+int board_late_init(void)
+{
+ if (IS_ENABLED(CONFIG_CMD_BMODE))
+ add_board_boot_modes(NULL);
+
+ if (IS_ENABLED(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)) {
+ const char *model;
+
+ model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+ if (model)
+ env_set("board_name", model);
+ }
+
+ return 0;
+}
diff --git a/configs/o4-imx6ull-nano_defconfig b/configs/o4-imx6ull-nano_defconfig
new file mode 100644
index 0000000000..906a3afe5d
--- /dev/null
+++ b/configs/o4-imx6ull-nano_defconfig
@@ -0,0 +1,103 @@
+CONFIG_ARCH_MX6=y
+CONFIG_ARM=y
+CONFIG_DEFAULT_DEVICE_TREE="o4-imx-nano"
+CONFIG_HUSH_PARSER=y
+CONFIG_IMX_MODULE_FUSE=y
+CONFIG_MX6ULL=y
+CONFIG_O4_IMX_NANO=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_IMX6=y
+CONFIG_SYS_TEXT_BASE=0x87800000
+CONFIG_TARGET_O4_IMX6ULL_NANO=y
+
+# CONFIG_K4B4G1646D_BCMA is not set
+CONFIG_MT41K256M16HA_125E=y
+
+# Device Tree
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIBFDT_OVERLAY=y
+
+# Environment
+CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
+CONFIG_ENV_IS_IN_FAT=y
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+
+# Clock driver for imx6ull is not implemented
+# CONFIG_CLK_IMX6Q=y
+
+# Thermal
+CONFIG_DM_THERMAL=y
+CONFIG_IMX_THERMAL=y
+
+# Serial
+CONFIG_DM_SERIAL=y
+CONFIG_MXC_UART=y
+
+# eMMC support
+CONFIG_CMD_MMC=y
+CONFIG_DM_MMC=y
+CONFIG_FSL_USDHC=y
+CONFIG_SUPPORT_EMMC_BOOT=y
+CONFIG_SUPPORT_EMMC_RPMB=y
+
+# GPIO support
+CONFIG_CMD_GPIO=y
+CONFIG_DM_GPIO=y
+CONFIG_MXC_GPIO=y
+
+# USB support
+CONFIG_CI_UDC=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+CONFIG_DM_USB=y
+CONFIG_USB=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+
+# Fastboot support
+CONFIG_CMD_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x82000000
+CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_USB_FUNCTION_FASTBOOT=y
+
+# Ethernet support
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MDIO=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_DM_ETH=y
+CONFIG_DM_ETH_PHY=y
+CONFIG_FEC_MXC=y
+CONFIG_FEC_MXC_MDIO_BASE=0x020b4000
+CONFIG_FEC_MXC_SHARE_MDIO=y
+CONFIG_MII=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_PHYLIB=y
+CONFIG_PHY_SMSC=y
+
+# I2C
+CONFIG_CMD_I2C=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MXC=y
+
+# Watchdog support is broken
+# CONFIG_CMD_WDT=y
+# CONFIG_IMX_WATCHDOG=y
+# CONFIG_SYSRESET_WATCHDOG=y
+# CONFIG_WATCHDOG_RESET_DISABLE=y
+# CONFIG_WDT=y
+
+# VBUS
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+
+# misc
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_PART=y
diff --git a/include/configs/o4-imx6ull-nano.h b/include/configs/o4-imx6ull-nano.h
new file mode 100644
index 0000000000..23308b6d01
--- /dev/null
+++ b/include/configs/o4-imx6ull-nano.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2021 Oleh Kravchenko <oleg(a)kaa.org.ua> */
+
+#ifndef __O4_IMX6ULL_NANO_CONFIG_H
+#define __O4_IMX6ULL_NANO_CONFIG_H
+
+#include "mx6_common.h"
+
+#define CONFIG_SYS_MALLOC_LEN (10 * SZ_1M)
+#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR
+#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM
+#define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR
+#define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE
+#define CONFIG_SYS_INIT_SP_OFFSET (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+
+#if IS_ENABLED(CONFIG_CMD_USB)
+# define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW)
+#endif /* CONFIG_CMD_USB */
+
+#if IS_ENABLED(CONFIG_FEC_MXC)
+# define CONFIG_FEC_XCV_TYPE RMII
+#endif /* CONFIG_FEC_MXC */
+
+#endif /* __O4_IMX6ULL_NANO_CONFIG_H */
--
2.26.3
1
1

[RFC PATCH] arm64: zynqmp: Add support for placing TFA from beginning of OCM
by Michal Simek 05 May '21
by Michal Simek 05 May '21
05 May '21
Xilinx TFA is normally placed to OCM at 0xfffea000 with a max size of 88kB.
By adding new and new features to TFA this split is reaching its limit
that there would be a need to change structures a little bit.
The idea is to resort SPL (potentially also Xilinx first stage bootloader
FSBL) that the beginning of the binary contains only the initcode which is
called only once before loading other images.
The way how this can be done is to use custom linker script and mark early
functions with __splinit to place them at the beginning of OCM.
Also make sure that space is bigger than current 88kB.
The patch is doing a barrier at 96kB just to prove that it is possible to
do so.
Code which is marked with __splinit is only coming from Xilinx Zynqmp code
but I would expect there is also generic code which can be marked like
that.
Signed-off-by: Michal Simek <michal.simek(a)xilinx.com>
---
Hi,
I am sending this series to start discussion how this can be done in a
better/generic way. Right now I have marked only the part of zynqmp code
which is just 0x3d54 = ~15kB of code. And then there is 81kB empty space
followed by generic code. Linux is marking this code with __init and this
is pretty much a similar idea to have it in the same location and being able
to reuse that location for different purposes
I expect all functions in include/init.h are exactly like that and there
will be likely others too.
Thanks,
Michal
---
arch/arm/mach-zynqmp/Kconfig | 3 +
arch/arm/mach-zynqmp/clk.c | 4 +-
arch/arm/mach-zynqmp/cpu.c | 6 +-
arch/arm/mach-zynqmp/handoff.c | 4 +-
.../mach-zynqmp/include/mach/psu_init_gpl.h | 21 ++---
arch/arm/mach-zynqmp/include/mach/sys_proto.h | 6 ++
arch/arm/mach-zynqmp/spl.c | 12 +--
arch/arm/mach-zynqmp/u-boot-spl.lds | 88 +++++++++++++++++++
board/xilinx/zynqmp/pm_cfg_obj.h | 4 +-
board/xilinx/zynqmp/zynqmp.c | 22 ++---
drivers/firmware/firmware-zynqmp.c | 4 +-
11 files changed, 136 insertions(+), 38 deletions(-)
create mode 100644 arch/arm/mach-zynqmp/u-boot-spl.lds
diff --git a/arch/arm/mach-zynqmp/Kconfig b/arch/arm/mach-zynqmp/Kconfig
index f1301f6661a1..8578c6910701 100644
--- a/arch/arm/mach-zynqmp/Kconfig
+++ b/arch/arm/mach-zynqmp/Kconfig
@@ -1,5 +1,8 @@
if ARCH_ZYNQMP
+config SPL_LDSCRIPT
+ default "arch/arm/mach-zynqmp/u-boot-spl.lds"
+
config SPL_FS_FAT
default y
diff --git a/arch/arm/mach-zynqmp/clk.c b/arch/arm/mach-zynqmp/clk.c
index 1e6e726e8792..ad2636169a1a 100644
--- a/arch/arm/mach-zynqmp/clk.c
+++ b/arch/arm/mach-zynqmp/clk.c
@@ -14,7 +14,7 @@
DECLARE_GLOBAL_DATA_PTR;
-unsigned long zynqmp_get_system_timer_freq(void)
+unsigned long __splinit zynqmp_get_system_timer_freq(void)
{
u32 ver = zynqmp_get_silicon_version();
@@ -35,7 +35,7 @@ unsigned long zynqmp_get_system_timer_freq(void)
* clock framework. The framework must not be used before this function had been
* called.
*/
-int set_cpu_clk_info(void)
+int __splinit set_cpu_clk_info(void)
{
gd->cpu_clk = get_tbclk();
diff --git a/arch/arm/mach-zynqmp/cpu.c b/arch/arm/mach-zynqmp/cpu.c
index 29743cae5aab..fa2d6e730cba 100644
--- a/arch/arm/mach-zynqmp/cpu.c
+++ b/arch/arm/mach-zynqmp/cpu.c
@@ -105,7 +105,7 @@ void mem_map_fill(void)
struct mm_region *mem_map = zynqmp_mem_map;
-u64 get_page_table_size(void)
+u64 __splinit get_page_table_size(void)
{
return 0x14000;
}
@@ -130,7 +130,7 @@ int arm_reserve_mmu(void)
}
#endif
-static unsigned int zynqmp_get_silicon_version_secure(void)
+static unsigned int __splinit zynqmp_get_silicon_version_secure(void)
{
u32 ver;
@@ -141,7 +141,7 @@ static unsigned int zynqmp_get_silicon_version_secure(void)
return ver;
}
-unsigned int zynqmp_get_silicon_version(void)
+unsigned int __splinit zynqmp_get_silicon_version(void)
{
if (current_el() == 3)
return zynqmp_get_silicon_version_secure();
diff --git a/arch/arm/mach-zynqmp/handoff.c b/arch/arm/mach-zynqmp/handoff.c
index 7d7ab9da6ec2..4c5a81fc4cad 100644
--- a/arch/arm/mach-zynqmp/handoff.c
+++ b/arch/arm/mach-zynqmp/handoff.c
@@ -72,7 +72,7 @@ struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry,
{
struct xfsbl_atf_handoff_params *atfhandoffparams;
- atfhandoffparams = (void *)CONFIG_SPL_TEXT_BASE;
+ atfhandoffparams = (void *)0xfffe0000;
atfhandoffparams->magic[0] = 'X';
atfhandoffparams->magic[1] = 'L';
atfhandoffparams->magic[2] = 'N';
@@ -86,7 +86,7 @@ struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry,
atfhandoffparams->num_entries++;
}
- writel(CONFIG_SPL_TEXT_BASE, &pmu_base->gen_storage6);
+ writel(0xfffe0000, &pmu_base->gen_storage6);
return NULL;
}
diff --git a/arch/arm/mach-zynqmp/include/mach/psu_init_gpl.h b/arch/arm/mach-zynqmp/include/mach/psu_init_gpl.h
index e37acda2f89e..9cccd2139700 100644
--- a/arch/arm/mach-zynqmp/include/mach/psu_init_gpl.h
+++ b/arch/arm/mach-zynqmp/include/mach/psu_init_gpl.h
@@ -5,22 +5,23 @@
#include <asm/io.h>
#include <common.h>
+#include <asm/arch/sys_proto.h>
-int mask_pollonvalue(unsigned long add, u32 mask, u32 value);
+int __splinit mask_pollonvalue(unsigned long add, u32 mask, u32 value);
-int mask_poll(u32 add, u32 mask);
+int __splinit mask_poll(u32 add, u32 mask);
-u32 mask_read(u32 add, u32 mask);
+u32 __splinit mask_read(u32 add, u32 mask);
-void mask_delay(u32 delay);
+void __splinit mask_delay(u32 delay);
-void psu_mask_write(unsigned long offset, unsigned long mask,
- unsigned long val);
+void __splinit psu_mask_write(unsigned long offset, unsigned long mask,
+ unsigned long val);
-void prog_reg(unsigned long addr, unsigned long mask,
- unsigned long shift, unsigned long value);
+void __splinit prog_reg(unsigned long addr, unsigned long mask,
+ unsigned long shift, unsigned long value);
-int psu_init(void);
-unsigned long psu_post_config_data(void);
+int __splinit psu_init(void);
+unsigned long __splinit psu_post_config_data(void);
#endif /* _PSU_INIT_GPL_H_ */
diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
index 1c12eac715e5..c1ab685c3ce4 100644
--- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h
+++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
@@ -7,6 +7,12 @@
#ifndef _ASM_ARCH_SYS_PROTO_H
#define _ASM_ARCH_SYS_PROTO_H
+#if CONFIG_SPL_BUILD
+#define __splinit __section(.splinit)
+#else
+#define __splinit
+#endif
+
#define ZYNQMP_CSU_SILICON_VER_MASK 0xF
#define KEY_PTR_LEN 32
#define IV_SIZE 12
diff --git a/arch/arm/mach-zynqmp/spl.c b/arch/arm/mach-zynqmp/spl.c
index 88386b23e5da..f57835143041 100644
--- a/arch/arm/mach-zynqmp/spl.c
+++ b/arch/arm/mach-zynqmp/spl.c
@@ -18,13 +18,13 @@
#include <asm/arch/psu_init_gpl.h>
#include <asm/arch/sys_proto.h>
-void board_init_f(ulong dummy)
+void __splinit board_init_f(ulong dummy)
{
board_early_init_f();
board_early_init_r();
}
-static void ps_mode_reset(ulong mode)
+static void __splinit ps_mode_reset(ulong mode)
{
writel(mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT,
&crlapb_base->boot_pin_ctrl);
@@ -43,7 +43,7 @@ static void ps_mode_reset(ulong mode)
#endif
#ifdef CONFIG_SPL_BOARD_INIT
-void spl_board_init(void)
+void __splinit spl_board_init(void)
{
preloader_console_init();
ps_mode_reset(MODE_RESET);
@@ -52,7 +52,7 @@ void spl_board_init(void)
}
#endif
-void board_boot_order(u32 *spl_boot_list)
+void __splinit board_boot_order(u32 *spl_boot_list)
{
spl_boot_list[0] = spl_boot_device();
@@ -64,7 +64,7 @@ void board_boot_order(u32 *spl_boot_list)
spl_boot_list[2] = BOOT_DEVICE_RAM;
}
-u32 spl_boot_device(void)
+u32 __splinit spl_boot_device(void)
{
u32 reg = 0;
u8 bootmode;
@@ -114,7 +114,7 @@ u32 spl_boot_device(void)
}
#ifdef CONFIG_SPL_OS_BOOT
-int spl_start_uboot(void)
+int __splinit spl_start_uboot(void)
{
return 0;
}
diff --git a/arch/arm/mach-zynqmp/u-boot-spl.lds b/arch/arm/mach-zynqmp/u-boot-spl.lds
new file mode 100644
index 000000000000..5b71d5a35142
--- /dev/null
+++ b/arch/arm/mach-zynqmp/u-boot-spl.lds
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2013
+ * David Feng <fenghua(a)phytium.com.cn>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj(a)denx.de>
+ *
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ * Aneesh V <aneesh(a)ti.com>
+ */
+
+MEMORY { .sram : ORIGIN = IMAGE_TEXT_BASE,
+ LENGTH = IMAGE_MAX_SIZE }
+MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR,
+ LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+SECTIONS
+{
+ .text : {
+ . = ALIGN(8);
+ *(.__image_copy_start)
+ CPUDIR/start.o (.text*)
+ *(.splinit*)
+ . = ALIGN(0x18000);
+ *(.text*)
+ } >.sram
+
+ .rodata : {
+ . = ALIGN(8);
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ } >.sram
+
+ .data : {
+ . = ALIGN(8);
+ *(.data*)
+ } >.sram
+
+#ifdef CONFIG_SPL_RECOVER_DATA_SECTION
+ .data_save : {
+ *(.__data_save_start)
+ . = SIZEOF(.data);
+ *(.__data_save_end)
+ } >.sram
+#endif
+
+ .u_boot_list : {
+ . = ALIGN(8);
+ KEEP(*(SORT(.u_boot_list*)));
+ } >.sram
+
+ .image_copy_end : {
+ . = ALIGN(8);
+ *(.__image_copy_end)
+ } >.sram
+
+ .end : {
+ . = ALIGN(8);
+ *(.__end)
+ } >.sram
+
+ _image_binary_end = .;
+
+ .bss_start (NOLOAD) : {
+ . = ALIGN(8);
+ KEEP(*(.__bss_start));
+ } >.sdram
+
+ .bss (NOLOAD) : {
+ *(.bss*)
+ . = ALIGN(8);
+ } >.sdram
+
+ .bss_end (NOLOAD) : {
+ KEEP(*(.__bss_end));
+ } >.sdram
+
+ /DISCARD/ : { *(.dynsym) }
+ /DISCARD/ : { *(.dynstr*) }
+ /DISCARD/ : { *(.dynamic*) }
+ /DISCARD/ : { *(.plt*) }
+ /DISCARD/ : { *(.interp*) }
+ /DISCARD/ : { *(.gnu*) }
+}
diff --git a/board/xilinx/zynqmp/pm_cfg_obj.h b/board/xilinx/zynqmp/pm_cfg_obj.h
index 86e785490ced..232dcd0ce116 100644
--- a/board/xilinx/zynqmp/pm_cfg_obj.h
+++ b/board/xilinx/zynqmp/pm_cfg_obj.h
@@ -5,5 +5,5 @@
* Declaration of PMU config object binary blob linked in at build time.
*/
-extern const u32 zynqmp_pm_cfg_obj[];
-extern const int zynqmp_pm_cfg_obj_size;
+extern const u32 __splinit zynqmp_pm_cfg_obj[];
+extern const int __splinit zynqmp_pm_cfg_obj_size;
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index d05f0b2e1202..e56cfa2cc520 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -185,7 +185,7 @@ static const struct {
},
};
-static char *zynqmp_get_silicon_idcode_name(void)
+static char __splinit *zynqmp_get_silicon_idcode_name(void)
{
u32 i;
u32 idcode, idcode2;
@@ -278,7 +278,7 @@ static char *zynqmp_get_silicon_idcode_name(void)
}
#endif
-int board_early_init_f(void)
+int __splinit board_early_init_f(void)
{
#if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED)
int ret;
@@ -300,7 +300,7 @@ int board_early_init_f(void)
return 0;
}
-static int multi_boot(void)
+static int __splinit multi_boot(void)
{
u32 multiboot;
@@ -314,7 +314,7 @@ static int multi_boot(void)
#define PS_SYSMON_ANALOG_BUS_VAL 0x3210
#define PS_SYSMON_ANALOG_BUS_REG 0xFFA50914
-int board_init(void)
+int __splinit board_init(void)
{
#if defined(CONFIG_ZYNQMP_FIRMWARE)
struct udevice *dev;
@@ -353,7 +353,7 @@ int board_init(void)
return 0;
}
-int board_early_init_r(void)
+int __splinit board_early_init_r(void)
{
u32 val;
@@ -396,7 +396,7 @@ unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
}
#if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
-int dram_init_banksize(void)
+int __splinit dram_init_banksize(void)
{
int ret;
@@ -409,7 +409,7 @@ int dram_init_banksize(void)
return 0;
}
-int dram_init(void)
+int __splinit dram_init(void)
{
if (fdtdec_setup_mem_size_base() != 0)
return -EINVAL;
@@ -417,7 +417,7 @@ int dram_init(void)
return 0;
}
#else
-int dram_init_banksize(void)
+int __splinit dram_init_banksize(void)
{
gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
gd->bd->bi_dram[0].size = get_effective_memsize();
@@ -427,7 +427,7 @@ int dram_init_banksize(void)
return 0;
}
-int dram_init(void)
+int __splinit dram_init(void)
{
gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
CONFIG_SYS_SDRAM_SIZE);
@@ -440,7 +440,7 @@ void reset_cpu(void)
{
}
-static u8 __maybe_unused zynqmp_get_bootmode(void)
+static u8 __maybe_unused __splinit zynqmp_get_bootmode(void)
{
u8 bootmode;
u32 reg = 0;
@@ -473,7 +473,7 @@ static const struct {
{}
};
-static int reset_reason(void)
+static int __splinit reset_reason(void)
{
u32 reg;
int i, ret;
diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
index d4dc856bafa4..08bcdf5bb024 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -55,7 +55,7 @@ static int ipi_req(const u32 *req, size_t req_len, u32 *res, size_t res_maxlen)
return ret;
}
-unsigned int zynqmp_firmware_version(void)
+unsigned int __splinit zynqmp_firmware_version(void)
{
int ret;
u32 ret_payload[PAYLOAD_ARG_CNT];
@@ -88,7 +88,7 @@ unsigned int zynqmp_firmware_version(void)
* @cfg_obj: Pointer to the configuration object
* @size: Size of @cfg_obj in bytes
*/
-void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size)
+void __splinit zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size)
{
int err;
u32 ret_payload[PAYLOAD_ARG_CNT];
--
2.31.1
1
0

[PATCH] MAINTAINERS: Update dhelectronics/dh_imx6/MAINTAINERS file
by Christoph Niedermaier 05 May '21
by Christoph Niedermaier 05 May '21
05 May '21
Adding new DH electronics mailing list and myself as a maintainer.
Signed-off-by: Christoph Niedermaier <cniedermaier(a)dh-electronics.com>
---
board/dhelectronics/dh_imx6/MAINTAINERS | 2 ++
1 file changed, 2 insertions(+)
diff --git a/board/dhelectronics/dh_imx6/MAINTAINERS b/board/dhelectronics/dh_imx6/MAINTAINERS
index ab4e16bd5d..60751e65ca 100644
--- a/board/dhelectronics/dh_imx6/MAINTAINERS
+++ b/board/dhelectronics/dh_imx6/MAINTAINERS
@@ -1,6 +1,8 @@
DH_IMX6 BOARD
M: Andreas Geisreiter <ageisreiter(a)dh-electronics.de>
M: Ludwig Zenz <lzenz(a)dh-electronics.de>
+M: Christoph Niedermaier <cniedermaier(a)dh-electronics.com>
+L: u-boot(a)dh-electronics.com
S: Maintained
F: board/dhelectronics/dh_imx6/
F: include/configs/dh_imx6.h
--
2.11.0
1
0
Hi Dimitri,
Thanks for looking into this.
On Tue, May 4, 2021 at 5:33 PM Dimitri John Ledkov
<dimitri.ledkov(a)canonical.com> wrote:
>
> Hi,
>
> On Thu, Apr 22, 2021 at 10:15 AM Green Wan <green.wan(a)sifive.com> wrote:
> >
> > From: David Abdurachmanov <david.abdurachmanov(a)sifive.com>
> >
> > Add fu740 support to macb ethernet driver
> >
> > There is a PLL HW quirk in FU740. The VSC8541XMV-02 specification
> > requires 125 +/-0.0125 Mhz. But the most close value can be output
> > by PLL is 125.125 MHz and out of VSC8541XMV-02 spec.
> >
>
> In the Linux kernel driver for this
> drivers/net/ethernet/cadence/macb_main.c it is not marked as
> compatible with "sifive,fu740-c000-gem" and it does not have a similar
> fix (and appears to use 125.0 MHz).
> Should a similar fix be contributed to the Linux kernel?
You're right. We also notice some refinement should be made here.
We're working on the way to solve it.
>
> As otherwise at the moment, one cannot pass the dtb from u-boot to
> linux, as that leads to loss of network since the kernel doesn't know
> about "sifive,fu740-c000-gem". If linux kernel contribution is not
> forthcoming, would it be possible to have u-boot dtb to be compatible
> with _both_ "sifive,fu540-c000-gem" and "sifive,fu740-c000-gem" on
> unmatched boards, such that if one (mistakenly) uses u-boots dtb with
> vanilla linux kernel networking still works? And then adjust the test
> to check for "sifive,fu740-c000-gem" compatible string first.
>
Not sure whether I get it correct. I think the best case is to have
Linux driver support both compatible string. And I'm a bit reluctant
to handle incorrect DTB passed situations. It might end up with
propagating issues and harder to trace back the root cause. I'll check
with colleagues and see if we can resolve that concern.
Thanks,
> > Signed-off-by: David Abdurachmanov <david.abdurachmanov(a)sifive.com>
> > Signed-off-by: Green Wan <green.wan(a)sifive.com>
> > Reviewed-by: Ramon Fried <rfried.dev(a)gmail.com>
> > Reviewed-by: Bin Meng <bmeng.cn(a)gmail.com>
> > ---
> > drivers/net/macb.c | 13 ++++++++++++-
> > 1 file changed, 12 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/macb.c b/drivers/net/macb.c
> > index 57ea45e2dc..bf70525c54 100644
> > --- a/drivers/net/macb.c
> > +++ b/drivers/net/macb.c
> > @@ -591,8 +591,17 @@ static int macb_sifive_clk_init(struct udevice *dev, ulong rate)
> > * 0 = GMII mode. Use 125 MHz gemgxlclk from PRCI in TX logic
> > * and output clock on GMII output signal GTX_CLK
> > * 1 = MII mode. Use MII input signal TX_CLK in TX logic
> > + *
> > + * FU740 have a PLL HW quirk. The 125.125 Mhz is actually out of
> > + * VSC8541XMV-02 specification. The tolerance level is +/-100ppm.
> > + * Which means the range should be in between 125MHz +/-0.0125.
> > + * But the most close value can be output by PLL is 125.125 MHz.
> > */
> > - writel(rate != 125000000, gemgxl_regs);
> > + if (device_is_compatible(dev, "sifive,fu540-c000-gem"))
> > + writel(rate != 125000000, gemgxl_regs);
> > + else if (device_is_compatible(dev, "sifive,fu740-c000-gem"))
> > + writel(rate != 125125000, gemgxl_regs);
> > +
> > return 0;
> > }
> >
> > @@ -1507,6 +1516,8 @@ static const struct udevice_id macb_eth_ids[] = {
> > { .compatible = "cdns,zynq-gem" },
> > { .compatible = "sifive,fu540-c000-gem",
> > .data = (ulong)&sifive_config },
> > + { .compatible = "sifive,fu740-c000-gem",
> > + .data = (ulong)&sifive_config },
> > { .compatible = "microchip,mpfs-mss-gem",
> > .data = (ulong)µchip_config },
> > { }
> > --
> > 2.31.0
> >
>
>
> --
> Regards,
>
> Dimitri.
2
1
Commit d9506cd41ce98e10a29c25c4766878367103bb2d attempts to fix ping in
netconsole [1] but IIUC the fix is incomplete (at least in our config).
[1] https://patchwork.ozlabs.org/project/uboot/patch/20201221034439.2747170-1-y…
Two issues were identified:
Firstly that the logic of eth_halt() in the various network operations
would break an already running netconsole.
Secondly, netconsole uses the net output buffer which means that any
nested network operation (such as arp or ping) will cause an overwrite
of the netconsole data.
Marked as RFC since not all network protocols have been tested, and not
all nc configurations have been tested (e.g. broadcast address).
Tested against ge_bx50v3_defconfig (i.MX6) using the fec.
Tested against 2020.10 050acee119b3757fee3bd128f55d720fdd9bb890, using a
configuration that includes CONFIG_NETCONSOLE, CONFIG_CMD_NFS, and
CONFIG_CMD_PING.
A sample session is as follows:
Configure (via serial console)
=> env set ethaddr ca:fe:de:ca:f0:11 ; env set ipaddr 192.168.120.49 ; setenv stdout serial,nc; setenv stdin serial,nc
=> env set ncip 192.168.120.1
Invoke net console
./netconsole 192.168.120.49
Invoke ping (via serial console)
=> ping 192.168.120.1
Using ethernet@2188000 device
host 192.168.120.1 is alive
=> _
Output on net console
Board out port: 6666
Board in port: 6666
NOTE: the interrupt signal (normally ^C) has been remapped to ^T
ncb: not found
=> ping 192.168.120.1
Using ethernet@2188000 device
host 192.168.120.1 is alive
=>
Invoke ping (via netconsole) for an IP address that is not reachable.
Type ^C to abort.
The ^C is not echoed.
=> ping 192.168.120.2
Using ethernet@2188000 device
Abort
ping failed; host 192.168.120.2 is not alive
=> _
Output on serial console
=> ping 192.168.120.2
Using ethernet@2188000 device
Abort
ping failed; host 192.168.120.2 is not alive
=>
The following tcpdump fragment captures the typing of the letters "ok"
in the net console. There was approximately 3 seconds between each
letter.
> sudo tcpdump -i enx001a9f0c4f04 -n host 192.168.120.49
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enx001a9f0c4f04, link-type EN10MB (Ethernet), capture size 262144 bytes
14:20:05.856372 IP 192.168.120.1.53891 > 192.168.120.49.6666: UDP, length 1
'o' from host (nc stdin) to target
14:20:05.856684 ARP, Request who-has 192.168.120.1 tell 192.168.120.49, length 46
14:20:05.856709 ARP, Reply 192.168.120.1 is-at 00:1a:9f:0c:4f:04, length 28
14:20:05.856981 IP 192.168.120.49.6666 > 192.168.120.1.6666: UDP, length 1
'o' from target (stdout) to host
14:20:06.626637 ARP, Request who-has 192.168.120.49 tell 192.168.120.1, length 28
14:20:06.626915 ARP, Reply 192.168.120.49 is-at ca:fe:de:ca:f0:11, length 46
14:20:09.364465 IP 192.168.120.1.53891 > 192.168.120.49.6666: UDP, length 1
'k' from host to target
14:20:09.364776 ARP, Request who-has 192.168.120.1 tell 192.168.120.49, length 46
14:20:09.364794 ARP, Reply 192.168.120.1 is-at 00:1a:9f:0c:4f:04, length 28
14:20:09.365041 IP 192.168.120.49.6666 > 192.168.120.1.6666: UDP, length 1
'k' from target to host
The following tcpdump fragment captures the typing of the letters "ok"
in the serial console. There was approximately 3 seconds between each
letter.
14:22:48.225004 ARP, Request who-has 192.168.120.1 tell 192.168.120.49, length 46
14:22:48.225032 ARP, Reply 192.168.120.1 is-at 00:1a:9f:0c:4f:04, length 28
14:22:48.225291 IP 192.168.120.49.6666 > 192.168.120.1.6666: UDP, length 1
'o' from target (stdout) to host
14:22:51.777002 ARP, Request who-has 192.168.120.1 tell 192.168.120.49, length 46
14:22:51.777031 ARP, Reply 192.168.120.1 is-at 00:1a:9f:0c:4f:04, length 28
14:22:51.777251 IP 192.168.120.49.6666 > 192.168.120.1.6666: UDP, length 1
'k' from target to host
The following tcpdump fragment captures ping to a known host.
(Not shown: the command "ping 192.168.120.1")
14:23:56.873103 ARP, Request who-has 192.168.120.1 tell 192.168.120.49, length 46
14:23:56.873131 ARP, Reply 192.168.120.1 is-at 00:1a:9f:0c:4f:04, length 28
14:23:56.873426 IP 192.168.120.49.6666 > 192.168.120.1.6666: UDP, length 1
'\n'
14:23:56.876020 IP 192.168.120.49.6666 > 192.168.120.1.6666: UDP, length 30
"Using ethernet@2188000 device"
14:23:56.876021 ARP, Request who-has 192.168.120.1 tell 192.168.120.49, length 46
14:23:56.876060 ARP, Reply 192.168.120.1 is-at 00:1a:9f:0c:4f:04, length 28
14:23:56.876354 IP 192.168.120.49 > 192.168.120.1: ICMP echo request, id 0, seq 5, length 8
14:23:56.876385 IP 192.168.120.1 > 192.168.120.49: ICMP echo reply, id 0, seq 5, length 8
14:23:56.879037 IP 192.168.120.49.6666 > 192.168.120.1.6666: UDP, length 28
"host 192.168.120.1 is alive"
14:23:56.879272 IP 192.168.120.49.6666 > 192.168.120.1.6666: UDP, length 3
"=> "
14:24:01.890653 ARP, Request who-has 192.168.120.49 tell 192.168.120.1, length 28
14:24:01.890933 ARP, Reply 192.168.120.49 is-at ca:fe:de:ca:f0:11, length 46
And, finally, the following tcpdump fragment captures ping to an unknown host.
(Not shown: the command "ping 192.168.120.2")
14:35:57.680889 ARP, Request who-has 192.168.120.2 tell 192.168.120.49, length 46
14:36:02.681255 ARP, Request who-has 192.168.120.2 tell 192.168.120.49, length 46
14:36:02.786656 ARP, Request who-has 192.168.120.49 tell 192.168.120.1, length 28
14:36:02.786953 ARP, Reply 192.168.120.49 is-at ca:fe:de:ca:f0:11, length 46
14:36:04.154698 IP 192.168.120.1.53891 > 192.168.120.49.6666: UDP, length 1
^C
14:36:04.155671 IP 192.168.120.49.6666 > 192.168.120.1.6666: UDP, length 7
"Abort"
14:36:04.159672 IP 192.168.120.49.6666 > 192.168.120.1.6666: UDP, length 45
"ping failed; host 192.168.120.2 is not alive"
14:36:04.159878 IP 192.168.120.49.6666 > 192.168.120.1.6666: UDP, length 3
"=> "
Ian Ray (2):
net: net_up, net_down
netconsole and networking co-existence
drivers/net/netconsole.c | 45 +++++++------------
include/net.h | 28 ++++--------
net/arp.c | 7 ++-
net/arp.h | 1 +
net/net.c | 111 ++++++++++++++++++++++++++++++++++-------------
net/ping.c | 4 +-
net/tftp.c | 4 --
net/wol.c | 1 -
8 files changed, 111 insertions(+), 90 deletions(-)
--
2.10.1
2
4
>From 7a3110962cd1482793a9912fa14e5d9961e9f01a Mon Sep 17 00:00:00 2001
From: "peng.wang(a)smartm.com" <peng.wang(a)smartm.com>
Date: Mon, 3 May 2021 23:53:29 -0700
Subject: [PATCH] cli: Fix command line underrun
This patch adds a column position check to fix the cli issue that
backspace doesn't stop at the prompt.
Signed-off-by: peng.wang(a)smartm.com <peng.wang(a)smartm.com>
---
common/cli_readline.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/common/cli_readline.c b/common/cli_readline.c
index c7614a4c90..bce670733f 100644
--- a/common/cli_readline.c
+++ b/common/cli_readline.c
@@ -45,8 +45,10 @@ static char *delete_char (char *buffer, char *p, int *colp, int *np, int plen)
}
}
} else {
- puts(erase_seq);
- (*colp)--;
+ if (*colp > plen) {
+ puts(erase_seq);
+ (*colp)--;
+ }
}
(*np)--;
--
2.31.1.windows.1
1
2
Thanks, I'll check the dependency.
On Tue, May 4, 2021 at 5:54 PM Dimitri John Ledkov
<dimitri.ledkov(a)canonical.com> wrote:
>
> "Hi,
>
> On Thu, Apr 22, 2021 at 10:15 AM Green Wan <green.wan(a)sifive.com> wrote:
> >
> > Add fu740 support. One abstract layer is added for supporting
> > multiple chips such as fu540 and fu740.
> >
> > Signed-off-by: Green Wan <green.wan(a)sifive.com>
> > ---
> > drivers/clk/sifive/Kconfig | 8 +-
> > drivers/clk/sifive/Makefile | 4 +-
> > drivers/clk/sifive/fu540-prci.c | 769 +------------------------------
> > drivers/clk/sifive/fu540-prci.h | 22 +
> > drivers/clk/sifive/fu740-prci.c | 158 +++++++
> > drivers/clk/sifive/fu740-prci.h | 22 +
> > drivers/clk/sifive/sifive-prci.c | 733 +++++++++++++++++++++++++++++
> > drivers/clk/sifive/sifive-prci.h | 323 +++++++++++++
> > 8 files changed, 1286 insertions(+), 753 deletions(-)
> > create mode 100644 drivers/clk/sifive/fu540-prci.h
> > create mode 100644 drivers/clk/sifive/fu740-prci.c
> > create mode 100644 drivers/clk/sifive/fu740-prci.h
> > create mode 100644 drivers/clk/sifive/sifive-prci.c
> > create mode 100644 drivers/clk/sifive/sifive-prci.h
> >
> > diff --git a/drivers/clk/sifive/Kconfig b/drivers/clk/sifive/Kconfig
> > index c4d0a1f9b1..20fc004b59 100644
> > --- a/drivers/clk/sifive/Kconfig
> > +++ b/drivers/clk/sifive/Kconfig
> > @@ -6,11 +6,11 @@ config CLK_SIFIVE
> > help
> > SoC drivers for SiFive Linux-capable SoCs.
> >
> > -config CLK_SIFIVE_FU540_PRCI
> > - bool "PRCI driver for SiFive FU540 SoCs"
> > +config CLK_SIFIVE_PRCI
> > + bool "PRCI driver for SiFive SoCs"
> > depends on CLK_SIFIVE
>
> Since the above is done in this patch, I would expect to remove all
> references to the CLK_SIFIVE_FU540_PRCI config option at the same
> time. Specifically:
>
> $ git grep CLK_SIFIVE_FU540_PRCI
> arch/riscv/cpu/fu540/Kconfig: imply CLK_SIFIVE_FU540_PRCI
> drivers/reset/Kconfig: depends on DM_RESET && CLK_SIFIVE_FU540_PRCI
> && TARGET_SIFIVE_UNLEASHED
>
> If above references were fixed, it remove the need to manually add
> "CONFIG_CLK_SIFIVE_PRCI=y" to unleashed config in the "board: sifive:
> add HiFive Unmatched board support" patch.
>
> Leaving left over references to the removed config options is
> confusing, and makes the patch not self contained.
>
>
> > select CLK_ANALOGBITS_WRPLL_CLN28HPC
> > help
> > Supports the Power Reset Clock interface (PRCI) IP block found in
> > - FU540 SoCs. If this kernel is meant to run on a SiFive FU540 SoC,
> > - enable this driver.
> > + FU540/FU740 SoCs. If this kernel is meant to run on a SiFive FU540/
> > + FU740 SoCs, enable this driver.
> > diff --git a/drivers/clk/sifive/Makefile b/drivers/clk/sifive/Makefile
> > index b224279afb..51348b1ddc 100644
> > --- a/drivers/clk/sifive/Makefile
> > +++ b/drivers/clk/sifive/Makefile
> > @@ -1,3 +1,5 @@
> > # SPDX-License-Identifier: GPL-2.0+
> >
> > -obj-$(CONFIG_CLK_SIFIVE_FU540_PRCI) += fu540-prci.o
> > +obj-y += sifive-prci.o
> > +
> > +obj-$(CONFIG_CLK_SIFIVE_PRCI) += fu540-prci.o fu740-prci.o
> > diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
> > index b3882d0b77..ceb2c6fab0 100644
> > --- a/drivers/clk/sifive/fu540-prci.c
> > +++ b/drivers/clk/sifive/fu540-prci.c
> > @@ -5,6 +5,8 @@
> > * Copyright (C) 2018 SiFive, Inc.
> > * Wesley Terpstra
> > * Paul Walmsley
> > + * Zong Li
> > + * Pragnesh Patel
> > *
> > * This program is free software; you can redistribute it and/or modify
> > * it under the terms of the GNU General Public License version 2 as
> > @@ -15,632 +17,48 @@
> > * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > * GNU General Public License for more details.
> > *
> > - * The FU540 PRCI implements clock and reset control for the SiFive
> > - * FU540-C000 chip. This driver assumes that it has sole control
> > - * over all PRCI resources.
> > - *
> > - * This driver is based on the PRCI driver written by Wesley Terpstra.
> > - *
> > - * Refer, commit 999529edf517ed75b56659d456d221b2ee56bb60 of:
> > - * https://github.com/riscv/riscv-linux
> > - *
> > * References:
> > * - SiFive FU540-C000 manual v1p0, Chapter 7 "Clocking and Reset"
> > */
> >
> > -#include <common.h>
> > -#include <clk-uclass.h>
> > -#include <clk.h>
> > -#include <div64.h>
> > -#include <dm.h>
> > -#include <dm/device.h>
> > -#include <dm/device_compat.h>
> > -#include <dm/uclass.h>
> > #include <dt-bindings/clock/sifive-fu540-prci.h>
> > -#include <dt-bindings/reset/sifive-fu540-prci.h>
> > -#include <errno.h>
> > -#include <reset-uclass.h>
> > -#include <asm/io.h>
> > -#include <asm/arch/reset.h>
> > -#include <linux/delay.h>
> > -#include <linux/err.h>
> > -#include <linux/math64.h>
> > -#include <linux/clk/analogbits-wrpll-cln28hpc.h>
> > -
> > -/*
> > - * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
> > - * hfclk and rtcclk
> > - */
> > -#define EXPECTED_CLK_PARENT_COUNT 2
> > -
> > -/*
> > - * Register offsets and bitmasks
> > - */
> > -
> > -/* COREPLLCFG0 */
> > -#define PRCI_COREPLLCFG0_OFFSET 0x4
> > -#define PRCI_COREPLLCFG0_DIVR_SHIFT 0
> > -#define PRCI_COREPLLCFG0_DIVR_MASK (0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT)
> > -#define PRCI_COREPLLCFG0_DIVF_SHIFT 6
> > -#define PRCI_COREPLLCFG0_DIVF_MASK (0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT)
> > -#define PRCI_COREPLLCFG0_DIVQ_SHIFT 15
> > -#define PRCI_COREPLLCFG0_DIVQ_MASK (0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT)
> > -#define PRCI_COREPLLCFG0_RANGE_SHIFT 18
> > -#define PRCI_COREPLLCFG0_RANGE_MASK (0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT)
> > -#define PRCI_COREPLLCFG0_BYPASS_SHIFT 24
> > -#define PRCI_COREPLLCFG0_BYPASS_MASK (0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT)
> > -#define PRCI_COREPLLCFG0_FSE_SHIFT 25
> > -#define PRCI_COREPLLCFG0_FSE_MASK (0x1 << PRCI_COREPLLCFG0_FSE_SHIFT)
> > -#define PRCI_COREPLLCFG0_LOCK_SHIFT 31
> > -#define PRCI_COREPLLCFG0_LOCK_MASK (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
> > -
> > -/* COREPLLCFG1 */
> > -#define PRCI_COREPLLCFG1_OFFSET 0x8
> > -#define PRCI_COREPLLCFG1_CKE_SHIFT 31
> > -#define PRCI_COREPLLCFG1_CKE_MASK (0x1 << PRCI_COREPLLCFG1_CKE_SHIFT)
> > -
> > -/* DDRPLLCFG0 */
> > -#define PRCI_DDRPLLCFG0_OFFSET 0xc
> > -#define PRCI_DDRPLLCFG0_DIVR_SHIFT 0
> > -#define PRCI_DDRPLLCFG0_DIVR_MASK (0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT)
> > -#define PRCI_DDRPLLCFG0_DIVF_SHIFT 6
> > -#define PRCI_DDRPLLCFG0_DIVF_MASK (0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT)
> > -#define PRCI_DDRPLLCFG0_DIVQ_SHIFT 15
> > -#define PRCI_DDRPLLCFG0_DIVQ_MASK (0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT)
> > -#define PRCI_DDRPLLCFG0_RANGE_SHIFT 18
> > -#define PRCI_DDRPLLCFG0_RANGE_MASK (0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT)
> > -#define PRCI_DDRPLLCFG0_BYPASS_SHIFT 24
> > -#define PRCI_DDRPLLCFG0_BYPASS_MASK (0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT)
> > -#define PRCI_DDRPLLCFG0_FSE_SHIFT 25
> > -#define PRCI_DDRPLLCFG0_FSE_MASK (0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT)
> > -#define PRCI_DDRPLLCFG0_LOCK_SHIFT 31
> > -#define PRCI_DDRPLLCFG0_LOCK_MASK (0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT)
> > -
> > -/* DDRPLLCFG1 */
> > -#define PRCI_DDRPLLCFG1_OFFSET 0x10
> > -#define PRCI_DDRPLLCFG1_CKE_SHIFT 31
> > -#define PRCI_DDRPLLCFG1_CKE_MASK (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
> > -
> > -/* GEMGXLPLLCFG0 */
> > -#define PRCI_GEMGXLPLLCFG0_OFFSET 0x1c
> > -#define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT 0
> > -#define PRCI_GEMGXLPLLCFG0_DIVR_MASK \
> > - (0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT)
> > -#define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT 6
> > -#define PRCI_GEMGXLPLLCFG0_DIVF_MASK \
> > - (0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT)
> > -#define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT 15
> > -#define PRCI_GEMGXLPLLCFG0_DIVQ_MASK (0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT)
> > -#define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT 18
> > -#define PRCI_GEMGXLPLLCFG0_RANGE_MASK \
> > - (0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT)
> > -#define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT 24
> > -#define PRCI_GEMGXLPLLCFG0_BYPASS_MASK \
> > - (0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT)
> > -#define PRCI_GEMGXLPLLCFG0_FSE_SHIFT 25
> > -#define PRCI_GEMGXLPLLCFG0_FSE_MASK \
> > - (0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT)
> > -#define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT 31
> > -#define PRCI_GEMGXLPLLCFG0_LOCK_MASK (0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT)
> > -
> > -/* GEMGXLPLLCFG1 */
> > -#define PRCI_GEMGXLPLLCFG1_OFFSET 0x20
> > -#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT 31
> > -#define PRCI_GEMGXLPLLCFG1_CKE_MASK (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
> > -
> > -/* CORECLKSEL */
> > -#define PRCI_CORECLKSEL_OFFSET 0x24
> > -#define PRCI_CORECLKSEL_CORECLKSEL_SHIFT 0
> > -#define PRCI_CORECLKSEL_CORECLKSEL_MASK \
> > - (0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT)
> > -
> > -/* DEVICESRESETREG */
> > -#define PRCI_DEVICESRESETREG_OFFSET 0x28
> > -#define PRCI_DEVICERESETCNT 5
> > -
> > -#define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK \
> > - (0x1 << PRCI_RST_DDR_CTRL_N)
> > -#define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK \
> > - (0x1 << PRCI_RST_DDR_AXI_N)
> > -#define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK \
> > - (0x1 << PRCI_RST_DDR_AHB_N)
> > -#define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK \
> > - (0x1 << PRCI_RST_DDR_PHY_N)
> > -#define PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK \
> > - (0x1 << PRCI_RST_GEMGXL_N)
> > -
> > -/* CLKMUXSTATUSREG */
> > -#define PRCI_CLKMUXSTATUSREG_OFFSET 0x2c
> > -#define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT 1
> > -#define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \
> > - (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
> > -
> > -/* PROCMONCFG */
> > -#define PRCI_PROCMONCFG_OFFSET 0xF0
> > -#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24
> > -#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
> > - (0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
> > -
> > -/*
> > - * Private structures
> > - */
> > -
> > -/**
> > - * struct __prci_data - per-device-instance data
> > - * @va: base virtual address of the PRCI IP block
> > - * @parent: parent clk instance
> > - *
> > - * PRCI per-device instance data
> > - */
> > -struct __prci_data {
> > - void *va;
> > - struct clk parent_hfclk;
> > - struct clk parent_rtcclk;
> > -};
> > -
> > -/**
> > - * struct __prci_wrpll_data - WRPLL configuration and integration data
> > - * @c: WRPLL current configuration record
> > - * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
> > - * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
> > - * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
> > - * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address
> > - * @release_reset: fn ptr to code to release clock reset
> > - *
> > - * @enable_bypass and @disable_bypass are used for WRPLL instances
> > - * that contain a separate external glitchless clock mux downstream
> > - * from the PLL. The WRPLL internal bypass mux is not glitchless.
> > - */
> > -struct __prci_wrpll_data {
> > - struct wrpll_cfg c;
> > - void (*enable_bypass)(struct __prci_data *pd);
> > - void (*disable_bypass)(struct __prci_data *pd);
> > - u8 cfg0_offs;
> > - u8 cfg1_offs;
> > - void (*release_reset)(struct __prci_data *pd);
> > -};
> > -
> > -struct __prci_clock;
> > -
> > -/* struct __prci_clock_ops - clock operations */
> > -struct __prci_clock_ops {
> > - int (*set_rate)(struct __prci_clock *pc,
> > - unsigned long rate,
> > - unsigned long parent_rate);
> > - unsigned long (*round_rate)(struct __prci_clock *pc,
> > - unsigned long rate,
> > - unsigned long *parent_rate);
> > - unsigned long (*recalc_rate)(struct __prci_clock *pc,
> > - unsigned long parent_rate);
> > - int (*enable_clk)(struct __prci_clock *pc, bool enable);
> > -};
> > -
> > -/**
> > - * struct __prci_clock - describes a clock device managed by PRCI
> > - * @name: user-readable clock name string - should match the manual
> > - * @parent_name: parent name for this clock
> > - * @ops: struct __prci_clock_ops for control
> > - * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
> > - * @pd: PRCI-specific data associated with this clock (if not NULL)
> > - *
> > - * PRCI clock data. Used by the PRCI driver to register PRCI-provided
> > - * clocks to the Linux clock infrastructure.
> > - */
> > -struct __prci_clock {
> > - const char *name;
> > - const char *parent_name;
> > - const struct __prci_clock_ops *ops;
> > - struct __prci_wrpll_data *pwd;
> > - struct __prci_data *pd;
> > -};
> > -
> > -/*
> > - * Private functions
> > - */
> > -
> > -/**
> > - * __prci_readl() - read from a PRCI register
> > - * @pd: PRCI context
> > - * @offs: register offset to read from (in bytes, from PRCI base address)
> > - *
> > - * Read the register located at offset @offs from the base virtual
> > - * address of the PRCI register target described by @pd, and return
> > - * the value to the caller.
> > - *
> > - * Context: Any context.
> > - *
> > - * Return: the contents of the register described by @pd and @offs.
> > - */
> > -static u32 __prci_readl(struct __prci_data *pd, u32 offs)
> > -{
> > - return readl(pd->va + offs);
> > -}
> > -
> > -static void __prci_writel(u32 v, u32 offs, struct __prci_data *pd)
> > -{
> > - writel(v, pd->va + offs);
> > -}
> > -
> > -/* WRPLL-related private functions */
> > -
> > -/**
> > - * __prci_wrpll_unpack() - unpack WRPLL configuration registers into parameters
> > - * @c: ptr to a struct wrpll_cfg record to write config into
> > - * @r: value read from the PRCI PLL configuration register
> > - *
> > - * Given a value @r read from an FU540 PRCI PLL configuration register,
> > - * split it into fields and populate it into the WRPLL configuration record
> > - * pointed to by @c.
> > - *
> > - * The COREPLLCFG0 macros are used below, but the other *PLLCFG0 macros
> > - * have the same register layout.
> > - *
> > - * Context: Any context.
> > - */
> > -static void __prci_wrpll_unpack(struct wrpll_cfg *c, u32 r)
> > -{
> > - u32 v;
> > -
> > - v = r & PRCI_COREPLLCFG0_DIVR_MASK;
> > - v >>= PRCI_COREPLLCFG0_DIVR_SHIFT;
> > - c->divr = v;
> > -
> > - v = r & PRCI_COREPLLCFG0_DIVF_MASK;
> > - v >>= PRCI_COREPLLCFG0_DIVF_SHIFT;
> > - c->divf = v;
> > -
> > - v = r & PRCI_COREPLLCFG0_DIVQ_MASK;
> > - v >>= PRCI_COREPLLCFG0_DIVQ_SHIFT;
> > - c->divq = v;
> > -
> > - v = r & PRCI_COREPLLCFG0_RANGE_MASK;
> > - v >>= PRCI_COREPLLCFG0_RANGE_SHIFT;
> > - c->range = v;
> > -
> > - c->flags &= (WRPLL_FLAGS_INT_FEEDBACK_MASK |
> > - WRPLL_FLAGS_EXT_FEEDBACK_MASK);
> > -
> > - /* external feedback mode not supported */
> > - c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
> > -}
> > -
> > -/**
> > - * __prci_wrpll_pack() - pack PLL configuration parameters into a register value
> > - * @c: pointer to a struct wrpll_cfg record containing the PLL's cfg
> > - *
> > - * Using a set of WRPLL configuration values pointed to by @c,
> > - * assemble a PRCI PLL configuration register value, and return it to
> > - * the caller.
> > - *
> > - * Context: Any context. Caller must ensure that the contents of the
> > - * record pointed to by @c do not change during the execution
> > - * of this function.
> > - *
> > - * Returns: a value suitable for writing into a PRCI PLL configuration
> > - * register
> > - */
> > -static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
> > -{
> > - u32 r = 0;
> > -
> > - r |= c->divr << PRCI_COREPLLCFG0_DIVR_SHIFT;
> > - r |= c->divf << PRCI_COREPLLCFG0_DIVF_SHIFT;
> > - r |= c->divq << PRCI_COREPLLCFG0_DIVQ_SHIFT;
> > - r |= c->range << PRCI_COREPLLCFG0_RANGE_SHIFT;
> > -
> > - /* external feedback mode not supported */
> > - r |= PRCI_COREPLLCFG0_FSE_MASK;
> > -
> > - return r;
> > -}
> > -
> > -/**
> > - * __prci_wrpll_read_cfg0() - read the WRPLL configuration from the PRCI
> > - * @pd: PRCI context
> > - * @pwd: PRCI WRPLL metadata
> > - *
> > - * Read the current configuration of the PLL identified by @pwd from
> > - * the PRCI identified by @pd, and store it into the local configuration
> > - * cache in @pwd.
> > - *
> > - * Context: Any context. Caller must prevent the records pointed to by
> > - * @pd and @pwd from changing during execution.
> > - */
> > -static void __prci_wrpll_read_cfg0(struct __prci_data *pd,
> > - struct __prci_wrpll_data *pwd)
> > -{
> > - __prci_wrpll_unpack(&pwd->c, __prci_readl(pd, pwd->cfg0_offs));
> > -}
> > -
> > -/**
> > - * __prci_wrpll_write_cfg0() - write WRPLL configuration into the PRCI
> > - * @pd: PRCI context
> > - * @pwd: PRCI WRPLL metadata
> > - * @c: WRPLL configuration record to write
> > - *
> > - * Write the WRPLL configuration described by @c into the WRPLL
> > - * configuration register identified by @pwd in the PRCI instance
> > - * described by @c. Make a cached copy of the WRPLL's current
> > - * configuration so it can be used by other code.
> > - *
> > - * Context: Any context. Caller must prevent the records pointed to by
> > - * @pd and @pwd from changing during execution.
> > - */
> > -static void __prci_wrpll_write_cfg0(struct __prci_data *pd,
> > - struct __prci_wrpll_data *pwd,
> > - struct wrpll_cfg *c)
> > -{
> > - __prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
> > -
> > - memcpy(&pwd->c, c, sizeof(*c));
> > -}
> > -
> > -/**
> > - * __prci_wrpll_write_cfg1() - write Clock enable/disable configuration
> > - * into the PRCI
> > - * @pd: PRCI context
> > - * @pwd: PRCI WRPLL metadata
> > - * @enable: Clock enable or disable value
> > - */
> > -static void __prci_wrpll_write_cfg1(struct __prci_data *pd,
> > - struct __prci_wrpll_data *pwd,
> > - u32 enable)
> > -{
> > - __prci_writel(enable, pwd->cfg1_offs, pd);
> > -}
> > -
> > -/* Core clock mux control */
> > -
> > -/**
> > - * __prci_coreclksel_use_hfclk() - switch the CORECLK mux to output HFCLK
> > - * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
> > - *
> > - * Switch the CORECLK mux to the HFCLK input source; return once complete.
> > - *
> > - * Context: Any context. Caller must prevent concurrent changes to the
> > - * PRCI_CORECLKSEL_OFFSET register.
> > - */
> > -static void __prci_coreclksel_use_hfclk(struct __prci_data *pd)
> > -{
> > - u32 r;
> > -
> > - r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
> > - r |= PRCI_CORECLKSEL_CORECLKSEL_MASK;
> > - __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
> > -
> > - r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
> > -}
> > -
> > -/**
> > - * __prci_coreclksel_use_corepll() - switch the CORECLK mux to output COREPLL
> > - * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
> > - *
> > - * Switch the CORECLK mux to the PLL output clock; return once complete.
> > - *
> > - * Context: Any context. Caller must prevent concurrent changes to the
> > - * PRCI_CORECLKSEL_OFFSET register.
> > - */
> > -static void __prci_coreclksel_use_corepll(struct __prci_data *pd)
> > -{
> > - u32 r;
> > -
> > - r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
> > - r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
> > - __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
> > -
> > - r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
> > -}
> > -
> > -static unsigned long sifive_fu540_prci_wrpll_recalc_rate(
> > - struct __prci_clock *pc,
> > - unsigned long parent_rate)
> > -{
> > - struct __prci_wrpll_data *pwd = pc->pwd;
> >
> > - return wrpll_calc_output_rate(&pwd->c, parent_rate);
> > -}
> > -
> > -static unsigned long sifive_fu540_prci_wrpll_round_rate(
> > - struct __prci_clock *pc,
> > - unsigned long rate,
> > - unsigned long *parent_rate)
> > -{
> > - struct __prci_wrpll_data *pwd = pc->pwd;
> > - struct wrpll_cfg c;
> > -
> > - memcpy(&c, &pwd->c, sizeof(c));
> > -
> > - wrpll_configure_for_rate(&c, rate, *parent_rate);
> > -
> > - return wrpll_calc_output_rate(&c, *parent_rate);
> > -}
> > -
> > -static int sifive_fu540_prci_wrpll_set_rate(struct __prci_clock *pc,
> > - unsigned long rate,
> > - unsigned long parent_rate)
> > -{
> > - struct __prci_wrpll_data *pwd = pc->pwd;
> > - struct __prci_data *pd = pc->pd;
> > - int r;
> > -
> > - r = wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
> > - if (r)
> > - return r;
> > -
> > - if (pwd->enable_bypass)
> > - pwd->enable_bypass(pd);
> > -
> > - __prci_wrpll_write_cfg0(pd, pwd, &pwd->c);
> > -
> > - udelay(wrpll_calc_max_lock_us(&pwd->c));
> > -
> > - if (pwd->disable_bypass)
> > - pwd->disable_bypass(pd);
> > -
> > - return 0;
> > -}
> > -
> > -static int sifive_fu540_prci_clock_enable(struct __prci_clock *pc, bool enable)
> > -{
> > - struct __prci_wrpll_data *pwd = pc->pwd;
> > - struct __prci_data *pd = pc->pd;
> > -
> > - if (enable) {
> > - __prci_wrpll_write_cfg1(pd, pwd, PRCI_COREPLLCFG1_CKE_MASK);
> > -
> > - if (pwd->release_reset)
> > - pwd->release_reset(pd);
> > - } else {
> > - u32 r;
> > -
> > - r = __prci_readl(pd, pwd->cfg1_offs);
> > - r &= ~PRCI_COREPLLCFG1_CKE_MASK;
> > -
> > - __prci_wrpll_write_cfg1(pd, pwd, r);
> > - }
> > -
> > - return 0;
> > -}
> > -
> > -static const struct __prci_clock_ops sifive_fu540_prci_wrpll_clk_ops = {
> > - .set_rate = sifive_fu540_prci_wrpll_set_rate,
> > - .round_rate = sifive_fu540_prci_wrpll_round_rate,
> > - .recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
> > - .enable_clk = sifive_fu540_prci_clock_enable,
> > -};
> > -
> > -/* TLCLKSEL clock integration */
> > -
> > -static unsigned long sifive_fu540_prci_tlclksel_recalc_rate(
> > - struct __prci_clock *pc,
> > - unsigned long parent_rate)
> > -{
> > - struct __prci_data *pd = pc->pd;
> > - u32 v;
> > - u8 div;
> > -
> > - v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
> > - v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
> > - div = v ? 1 : 2;
> > -
> > - return div_u64(parent_rate, div);
> > -}
> > -
> > -static const struct __prci_clock_ops sifive_fu540_prci_tlclksel_clk_ops = {
> > - .recalc_rate = sifive_fu540_prci_tlclksel_recalc_rate,
> > -};
> > -
> > -static int __prci_consumer_reset(const char *rst_name, bool trigger)
> > -{
> > - struct udevice *dev;
> > - struct reset_ctl rst_sig;
> > - int ret;
> > -
> > - ret = uclass_get_device_by_driver(UCLASS_RESET,
> > - DM_DRIVER_GET(sifive_reset),
> > - &dev);
> > - if (ret) {
> > - dev_err(dev, "Reset driver not found: %d\n", ret);
> > - return ret;
> > - }
> > -
> > - ret = reset_get_by_name(dev, rst_name, &rst_sig);
> > - if (ret) {
> > - dev_err(dev, "failed to get %s reset\n", rst_name);
> > - return ret;
> > - }
> > -
> > - if (reset_valid(&rst_sig)) {
> > - if (trigger)
> > - ret = reset_deassert(&rst_sig);
> > - else
> > - ret = reset_assert(&rst_sig);
> > - if (ret) {
> > - dev_err(dev, "failed to trigger reset id = %ld\n",
> > - rst_sig.id);
> > - return ret;
> > - }
> > - }
> > -
> > - return ret;
> > -}
> > -
> > -/**
> > - * __prci_ddr_release_reset() - Release DDR reset
> > - * @pd: struct __prci_data * for the PRCI containing the DDRCLK mux reg
> > - *
> > - */
> > -static void __prci_ddr_release_reset(struct __prci_data *pd)
> > -{
> > - /* Release DDR ctrl reset */
> > - __prci_consumer_reset("ddr_ctrl", true);
> > -
> > - /* HACK to get the '1 full controller clock cycle'. */
> > - asm volatile ("fence");
> > -
> > - /* Release DDR AXI reset */
> > - __prci_consumer_reset("ddr_axi", true);
> > -
> > - /* Release DDR AHB reset */
> > - __prci_consumer_reset("ddr_ahb", true);
> > -
> > - /* Release DDR PHY reset */
> > - __prci_consumer_reset("ddr_phy", true);
> > -
> > - /* HACK to get the '1 full controller clock cycle'. */
> > - asm volatile ("fence");
> > -
> > - /*
> > - * These take like 16 cycles to actually propagate. We can't go sending
> > - * stuff before they come out of reset. So wait.
> > - */
> > - for (int i = 0; i < 256; i++)
> > - asm volatile ("nop");
> > -}
> > -
> > -/**
> > - * __prci_ethernet_release_reset() - Release ethernet reset
> > - * @pd: struct __prci_data * for the PRCI containing the Ethernet CLK mux reg
> > - *
> > - */
> > -static void __prci_ethernet_release_reset(struct __prci_data *pd)
> > -{
> > - /* Release GEMGXL reset */
> > - __prci_consumer_reset("gemgxl_reset", true);
> > -
> > - /* Procmon => core clock */
> > - __prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK, PRCI_PROCMONCFG_OFFSET,
> > - pd);
> > -}
> > -
> > -/*
> > - * PRCI integration data for each WRPLL instance
> > - */
> > +#include "sifive-prci.h"
> >
> > +/* PRCI integration data for each WRPLL instance */
> > static struct __prci_wrpll_data __prci_corepll_data = {
> > .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
> > .cfg1_offs = PRCI_COREPLLCFG1_OFFSET,
> > - .enable_bypass = __prci_coreclksel_use_hfclk,
> > - .disable_bypass = __prci_coreclksel_use_corepll,
> > + .enable_bypass = sifive_prci_coreclksel_use_hfclk,
> > + .disable_bypass = sifive_prci_coreclksel_use_corepll,
> > };
> >
> > static struct __prci_wrpll_data __prci_ddrpll_data = {
> > .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
> > .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
> > - .release_reset = __prci_ddr_release_reset,
> > + .release_reset = sifive_prci_ddr_release_reset,
> > };
> >
> > static struct __prci_wrpll_data __prci_gemgxlpll_data = {
> > .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
> > .cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET,
> > - .release_reset = __prci_ethernet_release_reset,
> > + .release_reset = sifive_prci_ethernet_release_reset,
> > };
> >
> > -/*
> > - * List of clock controls provided by the PRCI
> > - */
> > +/* Linux clock framework integration */
> > +static const struct __prci_clock_ops sifive_fu540_prci_wrpll_clk_ops = {
> > + .set_rate = sifive_prci_wrpll_set_rate,
> > + .round_rate = sifive_prci_wrpll_round_rate,
> > + .recalc_rate = sifive_prci_wrpll_recalc_rate,
> > + .enable_clk = sifive_prci_clock_enable,
> > +};
> >
> > -static struct __prci_clock __prci_init_clocks[] = {
> > +static const struct __prci_clock_ops sifive_fu540_prci_tlclksel_clk_ops = {
> > + .recalc_rate = sifive_prci_tlclksel_recalc_rate,
> > +};
> > +
> > +/* List of clock controls provided by the PRCI */
> > +struct __prci_clock __prci_init_clocks_fu540[] = {
> > [PRCI_CLK_COREPLL] = {
> > .name = "corepll",
> > .parent_name = "hfclk",
> > @@ -665,148 +83,3 @@ static struct __prci_clock __prci_init_clocks[] = {
> > .ops = &sifive_fu540_prci_tlclksel_clk_ops,
> > },
> > };
> > -
> > -static ulong sifive_fu540_prci_parent_rate(struct __prci_clock *pc)
> > -{
> > - ulong parent_rate;
> > - struct __prci_clock *p;
> > -
> > - if (strcmp(pc->parent_name, "corepll") == 0) {
> > - p = &__prci_init_clocks[PRCI_CLK_COREPLL];
> > - if (!p->pd || !p->ops->recalc_rate)
> > - return -ENXIO;
> > -
> > - return p->ops->recalc_rate(p, sifive_fu540_prci_parent_rate(p));
> > - }
> > -
> > - if (strcmp(pc->parent_name, "rtcclk") == 0)
> > - parent_rate = clk_get_rate(&pc->pd->parent_rtcclk);
> > - else
> > - parent_rate = clk_get_rate(&pc->pd->parent_hfclk);
> > -
> > - return parent_rate;
> > -}
> > -
> > -static ulong sifive_fu540_prci_get_rate(struct clk *clk)
> > -{
> > - struct __prci_clock *pc;
> > -
> > - if (ARRAY_SIZE(__prci_init_clocks) <= clk->id)
> > - return -ENXIO;
> > -
> > - pc = &__prci_init_clocks[clk->id];
> > - if (!pc->pd || !pc->ops->recalc_rate)
> > - return -ENXIO;
> > -
> > - return pc->ops->recalc_rate(pc, sifive_fu540_prci_parent_rate(pc));
> > -}
> > -
> > -static ulong sifive_fu540_prci_set_rate(struct clk *clk, ulong rate)
> > -{
> > - int err;
> > - struct __prci_clock *pc;
> > -
> > - if (ARRAY_SIZE(__prci_init_clocks) <= clk->id)
> > - return -ENXIO;
> > -
> > - pc = &__prci_init_clocks[clk->id];
> > - if (!pc->pd || !pc->ops->set_rate)
> > - return -ENXIO;
> > -
> > - err = pc->ops->set_rate(pc, rate, sifive_fu540_prci_parent_rate(pc));
> > - if (err)
> > - return err;
> > -
> > - return rate;
> > -}
> > -
> > -static int sifive_fu540_prci_enable(struct clk *clk)
> > -{
> > - struct __prci_clock *pc;
> > - int ret = 0;
> > -
> > - if (ARRAY_SIZE(__prci_init_clocks) <= clk->id)
> > - return -ENXIO;
> > -
> > - pc = &__prci_init_clocks[clk->id];
> > - if (!pc->pd)
> > - return -ENXIO;
> > -
> > - if (pc->ops->enable_clk)
> > - ret = pc->ops->enable_clk(pc, 1);
> > -
> > - return ret;
> > -}
> > -
> > -static int sifive_fu540_prci_disable(struct clk *clk)
> > -{
> > - struct __prci_clock *pc;
> > - int ret = 0;
> > -
> > - if (ARRAY_SIZE(__prci_init_clocks) <= clk->id)
> > - return -ENXIO;
> > -
> > - pc = &__prci_init_clocks[clk->id];
> > - if (!pc->pd)
> > - return -ENXIO;
> > -
> > - if (pc->ops->enable_clk)
> > - ret = pc->ops->enable_clk(pc, 0);
> > -
> > - return ret;
> > -}
> > -
> > -static int sifive_fu540_prci_probe(struct udevice *dev)
> > -{
> > - int i, err;
> > - struct __prci_clock *pc;
> > - struct __prci_data *pd = dev_get_priv(dev);
> > -
> > - pd->va = (void *)dev_read_addr(dev);
> > - if (IS_ERR(pd->va))
> > - return PTR_ERR(pd->va);
> > -
> > - err = clk_get_by_index(dev, 0, &pd->parent_hfclk);
> > - if (err)
> > - return err;
> > -
> > - err = clk_get_by_index(dev, 1, &pd->parent_rtcclk);
> > - if (err)
> > - return err;
> > -
> > - for (i = 0; i < ARRAY_SIZE(__prci_init_clocks); ++i) {
> > - pc = &__prci_init_clocks[i];
> > - pc->pd = pd;
> > - if (pc->pwd)
> > - __prci_wrpll_read_cfg0(pd, pc->pwd);
> > - }
> > -
> > - return 0;
> > -}
> > -
> > -static struct clk_ops sifive_fu540_prci_ops = {
> > - .set_rate = sifive_fu540_prci_set_rate,
> > - .get_rate = sifive_fu540_prci_get_rate,
> > - .enable = sifive_fu540_prci_enable,
> > - .disable = sifive_fu540_prci_disable,
> > -};
> > -
> > -static int sifive_fu540_clk_bind(struct udevice *dev)
> > -{
> > - return sifive_reset_bind(dev, PRCI_DEVICERESETCNT);
> > -}
> > -
> > -static const struct udevice_id sifive_fu540_prci_ids[] = {
> > - { .compatible = "sifive,fu540-c000-prci" },
> > - { }
> > -};
> > -
> > -U_BOOT_DRIVER(sifive_fu540_prci) = {
> > - .name = "sifive-fu540-prci",
> > - .id = UCLASS_CLK,
> > - .of_match = sifive_fu540_prci_ids,
> > - .probe = sifive_fu540_prci_probe,
> > - .ops = &sifive_fu540_prci_ops,
> > - .priv_auto = sizeof(struct __prci_data),
> > - .bind = sifive_fu540_clk_bind,
> > -};
> > diff --git a/drivers/clk/sifive/fu540-prci.h b/drivers/clk/sifive/fu540-prci.h
> > new file mode 100644
> > index 0000000000..113301107d
> > --- /dev/null
> > +++ b/drivers/clk/sifive/fu540-prci.h
> > @@ -0,0 +1,22 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (C) 2020-2021 SiFive, Inc.
> > + * Zong Li
> > + * Pragnesh Patel
> > + */
> > +
> > +#ifndef __SIFIVE_CLK_FU540_PRCI_H
> > +#define __SIFIVE_CLK_FU540_PRCI_H
> > +
> > +#include "sifive-prci.h"
> > +
> > +#define NUM_CLOCK_FU540 4
> > +
> > +extern struct __prci_clock __prci_init_clocks_fu540[NUM_CLOCK_FU540];
> > +
> > +static const struct prci_clk_desc prci_clk_fu540 = {
> > + .clks = __prci_init_clocks_fu540,
> > + .num_clks = ARRAY_SIZE(__prci_init_clocks_fu540),
> > +};
> > +
> > +#endif /* __SIFIVE_CLK_FU540_PRCI_H */
> > diff --git a/drivers/clk/sifive/fu740-prci.c b/drivers/clk/sifive/fu740-prci.c
> > new file mode 100644
> > index 0000000000..9a642c1c99
> > --- /dev/null
> > +++ b/drivers/clk/sifive/fu740-prci.c
> > @@ -0,0 +1,158 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2018-2021 SiFive, Inc.
> > + * Wesley Terpstra
> > + * Paul Walmsley
> > + * Zong Li
> > + * Pragnesh Patel
> > + *
> > + * This program 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 program 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.
> > + */
> > +
> > +#include <dt-bindings/clock/sifive-fu740-prci.h>
> > +#include "sifive-prci.h"
> > +#include <asm/io.h>
> > +
> > +int sifive_prci_fu740_pciauxclk_enable(struct __prci_clock *pc, bool enable)
> > +{
> > + struct __prci_wrpll_data *pwd = pc->pwd;
> > + struct __prci_data *pd = pc->pd;
> > + u32 v;
> > +
> > + if (pwd->cfg1_offs != PRCI_PCIEAUXCFG1_OFFSET)
> > + return -EINVAL;
> > +
> > + v = readl(pd->va + pwd->cfg1_offs);
> > + v = enable ? (v | PRCI_PCIEAUXCFG1_MASK) : (v & ~PRCI_PCIEAUXCFG1_MASK);
> > + writel(v, pd->va + pwd->cfg1_offs);
> > +
> > + return 0;
> > +}
> > +
> > +/* PRCI integration data for each WRPLL instance */
> > +static struct __prci_wrpll_data __prci_corepll_data = {
> > + .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
> > + .cfg1_offs = PRCI_COREPLLCFG1_OFFSET,
> > + .enable_bypass = sifive_prci_coreclksel_use_hfclk,
> > + .disable_bypass = sifive_prci_coreclksel_use_final_corepll,
> > +};
> > +
> > +static struct __prci_wrpll_data __prci_ddrpll_data = {
> > + .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
> > + .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
> > + .release_reset = sifive_prci_ddr_release_reset,
> > +};
> > +
> > +static struct __prci_wrpll_data __prci_gemgxlpll_data = {
> > + .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
> > + .cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET,
> > + .release_reset = sifive_prci_ethernet_release_reset,
> > +};
> > +
> > +static struct __prci_wrpll_data __prci_dvfscorepll_data = {
> > + .cfg0_offs = PRCI_DVFSCOREPLLCFG0_OFFSET,
> > + .cfg1_offs = PRCI_DVFSCOREPLLCFG1_OFFSET,
> > + .enable_bypass = sifive_prci_corepllsel_use_corepll,
> > + .disable_bypass = sifive_prci_corepllsel_use_dvfscorepll,
> > +};
> > +
> > +static struct __prci_wrpll_data __prci_hfpclkpll_data = {
> > + .cfg0_offs = PRCI_HFPCLKPLLCFG0_OFFSET,
> > + .cfg1_offs = PRCI_HFPCLKPLLCFG1_OFFSET,
> > + .enable_bypass = sifive_prci_hfpclkpllsel_use_hfclk,
> > + .disable_bypass = sifive_prci_hfpclkpllsel_use_hfpclkpll,
> > +};
> > +
> > +static struct __prci_wrpll_data __prci_cltxpll_data = {
> > + .cfg0_offs = PRCI_CLTXPLLCFG0_OFFSET,
> > + .cfg1_offs = PRCI_CLTXPLLCFG1_OFFSET,
> > + .release_reset = sifive_prci_cltx_release_reset,
> > +};
> > +
> > +static struct __prci_wrpll_data __prci_pcieaux_data = {
> > + .cfg1_offs = PRCI_PCIEAUXCFG1_OFFSET,
> > +};
> > +
> > +/* Linux clock framework integration */
> > +
> > +static const struct __prci_clock_ops sifive_fu740_prci_wrpll_clk_ops = {
> > + .set_rate = sifive_prci_wrpll_set_rate,
> > + .round_rate = sifive_prci_wrpll_round_rate,
> > + .recalc_rate = sifive_prci_wrpll_recalc_rate,
> > + .enable_clk = sifive_prci_clock_enable,
> > +};
> > +
> > +static const struct __prci_clock_ops sifive_fu740_prci_tlclksel_clk_ops = {
> > + .recalc_rate = sifive_prci_tlclksel_recalc_rate,
> > +};
> > +
> > +static const struct __prci_clock_ops sifive_fu740_prci_hfpclkplldiv_clk_ops = {
> > + .recalc_rate = sifive_prci_hfpclkplldiv_recalc_rate,
> > +};
> > +
> > +static const struct __prci_clock_ops sifive_fu740_prci_pcieaux_clk_ops = {
> > + .enable_clk = sifive_prci_fu740_pciauxclk_enable,
> > +};
> > +
> > +/* List of clock controls provided by the PRCI */
> > +struct __prci_clock __prci_init_clocks_fu740[] = {
> > + [PRCI_CLK_COREPLL] = {
> > + .name = "corepll",
> > + .parent_name = "hfclk",
> > + .ops = &sifive_fu740_prci_wrpll_clk_ops,
> > + .pwd = &__prci_corepll_data,
> > + },
> > + [PRCI_CLK_DDRPLL] = {
> > + .name = "ddrpll",
> > + .parent_name = "hfclk",
> > + .ops = &sifive_fu740_prci_wrpll_clk_ops,
> > + .pwd = &__prci_ddrpll_data,
> > + },
> > + [PRCI_CLK_GEMGXLPLL] = {
> > + .name = "gemgxlpll",
> > + .parent_name = "hfclk",
> > + .ops = &sifive_fu740_prci_wrpll_clk_ops,
> > + .pwd = &__prci_gemgxlpll_data,
> > + },
> > + [PRCI_CLK_DVFSCOREPLL] = {
> > + .name = "dvfscorepll",
> > + .parent_name = "hfclk",
> > + .ops = &sifive_fu740_prci_wrpll_clk_ops,
> > + .pwd = &__prci_dvfscorepll_data,
> > + },
> > + [PRCI_CLK_HFPCLKPLL] = {
> > + .name = "hfpclkpll",
> > + .parent_name = "hfclk",
> > + .ops = &sifive_fu740_prci_wrpll_clk_ops,
> > + .pwd = &__prci_hfpclkpll_data,
> > + },
> > + [PRCI_CLK_CLTXPLL] = {
> > + .name = "cltxpll",
> > + .parent_name = "hfclk",
> > + .ops = &sifive_fu740_prci_wrpll_clk_ops,
> > + .pwd = &__prci_cltxpll_data,
> > + },
> > + [PRCI_CLK_TLCLK] = {
> > + .name = "tlclk",
> > + .parent_name = "corepll",
> > + .ops = &sifive_fu740_prci_tlclksel_clk_ops,
> > + },
> > + [PRCI_CLK_PCLK] = {
> > + .name = "pclk",
> > + .parent_name = "hfpclkpll",
> > + .ops = &sifive_fu740_prci_hfpclkplldiv_clk_ops,
> > + },
> > + [PRCI_CLK_PCIEAUX] {
> > + .name = "pciaux",
> > + .parent_name = "",
> > + .ops = &sifive_fu740_prci_pcieaux_clk_ops,
> > + .pwd = &__prci_pcieaux_data,
> > + }
> > +};
> > diff --git a/drivers/clk/sifive/fu740-prci.h b/drivers/clk/sifive/fu740-prci.h
> > new file mode 100644
> > index 0000000000..b74f078906
> > --- /dev/null
> > +++ b/drivers/clk/sifive/fu740-prci.h
> > @@ -0,0 +1,22 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (C) 2020-2021 SiFive, Inc.
> > + * Zong Li
> > + * Pragnesh Patel
> > + */
> > +
> > +#ifndef __SIFIVE_CLK_FU740_PRCI_H
> > +#define __SIFIVE_CLK_FU740_PRCI_H
> > +
> > +#include "sifive-prci.h"
> > +
> > +#define NUM_CLOCK_FU740 9
> > +
> > +extern struct __prci_clock __prci_init_clocks_fu740[NUM_CLOCK_FU740];
> > +
> > +static const struct prci_clk_desc prci_clk_fu740 = {
> > + .clks = __prci_init_clocks_fu740,
> > + .num_clks = ARRAY_SIZE(__prci_init_clocks_fu740),
> > +};
> > +
> > +#endif /* __SIFIVE_CLK_FU740_PRCI_H */
> > diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c
> > new file mode 100644
> > index 0000000000..cd1acb9442
> > --- /dev/null
> > +++ b/drivers/clk/sifive/sifive-prci.c
> > @@ -0,0 +1,733 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2018-2021 SiFive, Inc.
> > + * Wesley Terpstra
> > + * Paul Walmsley
> > + * Zong Li
> > + * Pragnesh Patel
> > + *
> > + * This program 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 program 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.
> > + *
> > + * The PRCI implements clock and reset control for the SiFive chip.
> > + * This driver assumes that it has sole control over all PRCI resources.
> > + *
> > + * This driver is based on the PRCI driver written by Wesley Terpstra:
> > + * https://github.com/riscv/riscv-linux/commit/999529edf517ed75b56659d456d221b…
> > + */
> > +
> > +#include <common.h>
> > +#include <clk-uclass.h>
> > +#include <clk.h>
> > +#include <dm.h>
> > +#include <dm/device_compat.h>
> > +#include <reset.h>
> > +#include <asm/io.h>
> > +#include <asm/arch/reset.h>
> > +#include <linux/delay.h>
> > +#include <linux/math64.h>
> > +#include <dt-bindings/clock/sifive-fu740-prci.h>
> > +
> > +#include "fu540-prci.h"
> > +#include "fu740-prci.h"
> > +
> > +/*
> > + * Private functions
> > + */
> > +
> > +/**
> > + * __prci_readl() - read from a PRCI register
> > + * @pd: PRCI context
> > + * @offs: register offset to read from (in bytes, from PRCI base address)
> > + *
> > + * Read the register located at offset @offs from the base virtual
> > + * address of the PRCI register target described by @pd, and return
> > + * the value to the caller.
> > + *
> > + * Context: Any context.
> > + *
> > + * Return: the contents of the register described by @pd and @offs.
> > + */
> > +static u32 __prci_readl(struct __prci_data *pd, u32 offs)
> > +{
> > + return readl(pd->va + offs);
> > +}
> > +
> > +static void __prci_writel(u32 v, u32 offs, struct __prci_data *pd)
> > +{
> > + writel(v, pd->va + offs);
> > +}
> > +
> > +/* WRPLL-related private functions */
> > +
> > +/**
> > + * __prci_wrpll_unpack() - unpack WRPLL configuration registers into parameters
> > + * @c: ptr to a struct wrpll_cfg record to write config into
> > + * @r: value read from the PRCI PLL configuration register
> > + *
> > + * Given a value @r read from an FU540 PRCI PLL configuration register,
> > + * split it into fields and populate it into the WRPLL configuration record
> > + * pointed to by @c.
> > + *
> > + * The COREPLLCFG0 macros are used below, but the other *PLLCFG0 macros
> > + * have the same register layout.
> > + *
> > + * Context: Any context.
> > + */
> > +static void __prci_wrpll_unpack(struct wrpll_cfg *c, u32 r)
> > +{
> > + u32 v;
> > +
> > + v = r & PRCI_COREPLLCFG0_DIVR_MASK;
> > + v >>= PRCI_COREPLLCFG0_DIVR_SHIFT;
> > + c->divr = v;
> > +
> > + v = r & PRCI_COREPLLCFG0_DIVF_MASK;
> > + v >>= PRCI_COREPLLCFG0_DIVF_SHIFT;
> > + c->divf = v;
> > +
> > + v = r & PRCI_COREPLLCFG0_DIVQ_MASK;
> > + v >>= PRCI_COREPLLCFG0_DIVQ_SHIFT;
> > + c->divq = v;
> > +
> > + v = r & PRCI_COREPLLCFG0_RANGE_MASK;
> > + v >>= PRCI_COREPLLCFG0_RANGE_SHIFT;
> > + c->range = v;
> > +
> > + c->flags &= (WRPLL_FLAGS_INT_FEEDBACK_MASK |
> > + WRPLL_FLAGS_EXT_FEEDBACK_MASK);
> > +
> > + /* external feedback mode not supported */
> > + c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
> > +}
> > +
> > +/**
> > + * __prci_wrpll_pack() - pack PLL configuration parameters into a register value
> > + * @c: pointer to a struct wrpll_cfg record containing the PLL's cfg
> > + *
> > + * Using a set of WRPLL configuration values pointed to by @c,
> > + * assemble a PRCI PLL configuration register value, and return it to
> > + * the caller.
> > + *
> > + * Context: Any context. Caller must ensure that the contents of the
> > + * record pointed to by @c do not change during the execution
> > + * of this function.
> > + *
> > + * Returns: a value suitable for writing into a PRCI PLL configuration
> > + * register
> > + */
> > +static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
> > +{
> > + u32 r = 0;
> > +
> > + r |= c->divr << PRCI_COREPLLCFG0_DIVR_SHIFT;
> > + r |= c->divf << PRCI_COREPLLCFG0_DIVF_SHIFT;
> > + r |= c->divq << PRCI_COREPLLCFG0_DIVQ_SHIFT;
> > + r |= c->range << PRCI_COREPLLCFG0_RANGE_SHIFT;
> > +
> > + /* external feedback mode not supported */
> > + r |= PRCI_COREPLLCFG0_FSE_MASK;
> > +
> > + return r;
> > +}
> > +
> > +/**
> > + * __prci_wrpll_read_cfg0() - read the WRPLL configuration from the PRCI
> > + * @pd: PRCI context
> > + * @pwd: PRCI WRPLL metadata
> > + *
> > + * Read the current configuration of the PLL identified by @pwd from
> > + * the PRCI identified by @pd, and store it into the local configuration
> > + * cache in @pwd.
> > + *
> > + * Context: Any context. Caller must prevent the records pointed to by
> > + * @pd and @pwd from changing during execution.
> > + */
> > +static void __prci_wrpll_read_cfg0(struct __prci_data *pd,
> > + struct __prci_wrpll_data *pwd)
> > +{
> > + __prci_wrpll_unpack(&pwd->c, __prci_readl(pd, pwd->cfg0_offs));
> > +}
> > +
> > +/**
> > + * __prci_wrpll_write_cfg0() - write WRPLL configuration into the PRCI
> > + * @pd: PRCI context
> > + * @pwd: PRCI WRPLL metadata
> > + * @c: WRPLL configuration record to write
> > + *
> > + * Write the WRPLL configuration described by @c into the WRPLL
> > + * configuration register identified by @pwd in the PRCI instance
> > + * described by @c. Make a cached copy of the WRPLL's current
> > + * configuration so it can be used by other code.
> > + *
> > + * Context: Any context. Caller must prevent the records pointed to by
> > + * @pd and @pwd from changing during execution.
> > + */
> > +static void __prci_wrpll_write_cfg0(struct __prci_data *pd,
> > + struct __prci_wrpll_data *pwd,
> > + struct wrpll_cfg *c)
> > +{
> > + __prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
> > +
> > + memcpy(&pwd->c, c, sizeof(*c));
> > +}
> > +
> > +/**
> > + * __prci_wrpll_write_cfg1() - write Clock enable/disable configuration
> > + * into the PRCI
> > + * @pd: PRCI context
> > + * @pwd: PRCI WRPLL metadata
> > + * @enable: Clock enable or disable value
> > + */
> > +static void __prci_wrpll_write_cfg1(struct __prci_data *pd,
> > + struct __prci_wrpll_data *pwd,
> > + u32 enable)
> > +{
> > + __prci_writel(enable, pwd->cfg1_offs, pd);
> > +}
> > +
> > +unsigned long sifive_prci_wrpll_recalc_rate(struct __prci_clock *pc,
> > + unsigned long parent_rate)
> > +{
> > + struct __prci_wrpll_data *pwd = pc->pwd;
> > +
> > + return wrpll_calc_output_rate(&pwd->c, parent_rate);
> > +}
> > +
> > +unsigned long sifive_prci_wrpll_round_rate(struct __prci_clock *pc,
> > + unsigned long rate,
> > + unsigned long *parent_rate)
> > +{
> > + struct __prci_wrpll_data *pwd = pc->pwd;
> > + struct wrpll_cfg c;
> > +
> > + memcpy(&c, &pwd->c, sizeof(c));
> > +
> > + wrpll_configure_for_rate(&c, rate, *parent_rate);
> > +
> > + return wrpll_calc_output_rate(&c, *parent_rate);
> > +}
> > +
> > +int sifive_prci_wrpll_set_rate(struct __prci_clock *pc,
> > + unsigned long rate,
> > + unsigned long parent_rate)
> > +{
> > + struct __prci_wrpll_data *pwd = pc->pwd;
> > + struct __prci_data *pd = pc->pd;
> > + int r;
> > +
> > + r = wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
> > + if (r)
> > + return r;
> > +
> > + if (pwd->enable_bypass)
> > + pwd->enable_bypass(pd);
> > +
> > + __prci_wrpll_write_cfg0(pd, pwd, &pwd->c);
> > +
> > + udelay(wrpll_calc_max_lock_us(&pwd->c));
> > +
> > + return 0;
> > +}
> > +
> > +int sifive_prci_clock_enable(struct __prci_clock *pc, bool enable)
> > +{
> > + struct __prci_wrpll_data *pwd = pc->pwd;
> > + struct __prci_data *pd = pc->pd;
> > +
> > + if (enable) {
> > + __prci_wrpll_write_cfg1(pd, pwd, PRCI_COREPLLCFG1_CKE_MASK);
> > +
> > + if (pwd->disable_bypass)
> > + pwd->disable_bypass(pd);
> > +
> > + if (pwd->release_reset)
> > + pwd->release_reset(pd);
> > + } else {
> > + u32 r;
> > +
> > + if (pwd->enable_bypass)
> > + pwd->enable_bypass(pd);
> > +
> > + r = __prci_readl(pd, pwd->cfg1_offs);
> > + r &= ~PRCI_COREPLLCFG1_CKE_MASK;
> > +
> > + __prci_wrpll_write_cfg1(pd, pwd, r);
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +/* TLCLKSEL clock integration */
> > +
> > +unsigned long sifive_prci_tlclksel_recalc_rate(struct __prci_clock *pc,
> > + unsigned long parent_rate)
> > +{
> > + struct __prci_data *pd = pc->pd;
> > + u32 v;
> > + u8 div;
> > +
> > + v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
> > + v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
> > + div = v ? 1 : 2;
> > +
> > + return div_u64(parent_rate, div);
> > +}
> > +
> > +/* HFPCLK clock integration */
> > +
> > +unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct __prci_clock *pc,
> > + unsigned long parent_rate)
> > +{
> > + struct __prci_data *pd = pc->pd;
> > + u32 div = __prci_readl(pd, PRCI_HFPCLKPLLDIV_OFFSET);
> > +
> > + return div_u64(parent_rate, div + 2);
> > +}
> > +
> > +/**
> > + * sifive_prci_coreclksel_use_final_corepll() - switch the CORECLK mux to output
> > + * FINAL_COREPLL
> > + * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
> > + *
> > + * Switch the CORECLK mux to the final COREPLL output clock; return once
> > + * complete.
> > + *
> > + * Context: Any context. Caller must prevent concurrent changes to the
> > + * PRCI_CORECLKSEL_OFFSET register.
> > + */
> > +void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd)
> > +{
> > + u32 r;
> > +
> > + r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
> > + r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
> > + __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
> > +
> > + r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
> > +}
> > +
> > +/**
> > + * sifive_prci_corepllsel_use_dvfscorepll() - switch the COREPLL mux to
> > + * output DVFS_COREPLL
> > + * @pd: struct __prci_data * for the PRCI containing the COREPLL mux reg
> > + *
> > + * Switch the COREPLL mux to the DVFSCOREPLL output clock; return once complete.
> > + *
> > + * Context: Any context. Caller must prevent concurrent changes to the
> > + * PRCI_COREPLLSEL_OFFSET register.
> > + */
> > +void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd)
> > +{
> > + u32 r;
> > +
> > + r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET);
> > + r |= PRCI_COREPLLSEL_COREPLLSEL_MASK;
> > + __prci_writel(r, PRCI_COREPLLSEL_OFFSET, pd);
> > +
> > + r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET); /* barrier */
> > +}
> > +
> > +/**
> > + * sifive_prci_corepllsel_use_corepll() - switch the COREPLL mux to
> > + * output COREPLL
> > + * @pd: struct __prci_data * for the PRCI containing the COREPLL mux reg
> > + *
> > + * Switch the COREPLL mux to the COREPLL output clock; return once complete.
> > + *
> > + * Context: Any context. Caller must prevent concurrent changes to the
> > + * PRCI_COREPLLSEL_OFFSET register.
> > + */
> > +void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd)
> > +{
> > + u32 r;
> > +
> > + r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET);
> > + r &= ~PRCI_COREPLLSEL_COREPLLSEL_MASK;
> > + __prci_writel(r, PRCI_COREPLLSEL_OFFSET, pd);
> > +
> > + r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET); /* barrier */
> > +}
> > +
> > +/**
> > + * sifive_prci_hfpclkpllsel_use_hfclk() - switch the HFPCLKPLL mux to
> > + * output HFCLK
> > + * @pd: struct __prci_data * for the PRCI containing the HFPCLKPLL mux reg
> > + *
> > + * Switch the HFPCLKPLL mux to the HFCLK input source; return once complete.
> > + *
> > + * Context: Any context. Caller must prevent concurrent changes to the
> > + * PRCI_HFPCLKPLLSEL_OFFSET register.
> > + */
> > +void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd)
> > +{
> > + u32 r;
> > +
> > + r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET);
> > + r |= PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK;
> > + __prci_writel(r, PRCI_HFPCLKPLLSEL_OFFSET, pd);
> > +
> > + r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); /* barrier */
> > +}
> > +
> > +/**
> > + * sifive_prci_hfpclkpllsel_use_hfpclkpll() - switch the HFPCLKPLL mux to
> > + * output HFPCLKPLL
> > + * @pd: struct __prci_data * for the PRCI containing the HFPCLKPLL mux reg
> > + *
> > + * Switch the HFPCLKPLL mux to the HFPCLKPLL output clock; return once complete.
> > + *
> > + * Context: Any context. Caller must prevent concurrent changes to the
> > + * PRCI_HFPCLKPLLSEL_OFFSET register.
> > + */
> > +void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd)
> > +{
> > + u32 r;
> > +
> > + r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET);
> > + r &= ~PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK;
> > + __prci_writel(r, PRCI_HFPCLKPLLSEL_OFFSET, pd);
> > +
> > + r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); /* barrier */
> > +}
> > +
> > +static int __prci_consumer_reset(const char *rst_name, bool trigger)
> > +{
> > + struct udevice *dev;
> > + struct reset_ctl rst_sig;
> > + int ret;
> > +
> > + ret = uclass_get_device_by_driver(UCLASS_RESET,
> > + DM_DRIVER_GET(sifive_reset),
> > + &dev);
> > + if (ret) {
> > + dev_err(dev, "Reset driver not found: %d\n", ret);
> > + return ret;
> > + }
> > +
> > + ret = reset_get_by_name(dev, rst_name, &rst_sig);
> > + if (ret) {
> > + dev_err(dev, "failed to get %s reset\n", rst_name);
> > + return ret;
> > + }
> > +
> > + if (reset_valid(&rst_sig)) {
> > + if (trigger)
> > + ret = reset_deassert(&rst_sig);
> > + else
> > + ret = reset_assert(&rst_sig);
> > + if (ret) {
> > + dev_err(dev, "failed to trigger reset id = %ld\n",
> > + rst_sig.id);
> > + return ret;
> > + }
> > + }
> > +
> > + return ret;
> > +}
> > +
> > +/**
> > + * sifive_prci_ddr_release_reset() - Release DDR reset
> > + * @pd: struct __prci_data * for the PRCI containing the DDRCLK mux reg
> > + *
> > + */
> > +void sifive_prci_ddr_release_reset(struct __prci_data *pd)
> > +{
> > + /* Release DDR ctrl reset */
> > + __prci_consumer_reset("ddr_ctrl", true);
> > +
> > + /* HACK to get the '1 full controller clock cycle'. */
> > + asm volatile ("fence");
> > +
> > + /* Release DDR AXI reset */
> > + __prci_consumer_reset("ddr_axi", true);
> > +
> > + /* Release DDR AHB reset */
> > + __prci_consumer_reset("ddr_ahb", true);
> > +
> > + /* Release DDR PHY reset */
> > + __prci_consumer_reset("ddr_phy", true);
> > +
> > + /* HACK to get the '1 full controller clock cycle'. */
> > + asm volatile ("fence");
> > +
> > + /*
> > + * These take like 16 cycles to actually propagate. We can't go sending
> > + * stuff before they come out of reset. So wait.
> > + */
> > + for (int i = 0; i < 256; i++)
> > + asm volatile ("nop");
> > +}
> > +
> > +/**
> > + * sifive_prci_ethernet_release_reset() - Release ethernet reset
> > + * @pd: struct __prci_data * for the PRCI containing the Ethernet CLK mux reg
> > + *
> > + */
> > +void sifive_prci_ethernet_release_reset(struct __prci_data *pd)
> > +{
> > + /* Release GEMGXL reset */
> > + __prci_consumer_reset("gemgxl_reset", true);
> > +
> > + /* Procmon => core clock */
> > + __prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK, PRCI_PROCMONCFG_OFFSET,
> > + pd);
> > +
> > + /* Release Chiplink reset */
> > + __prci_consumer_reset("cltx_reset", true);
> > +}
> > +
> > +/**
> > + * sifive_prci_cltx_release_reset() - Release cltx reset
> > + * @pd: struct __prci_data * for the PRCI containing the Ethernet CLK mux reg
> > + *
> > + */
> > +void sifive_prci_cltx_release_reset(struct __prci_data *pd)
> > +{
> > + /* Release CLTX reset */
> > + __prci_consumer_reset("cltx_reset", true);
> > +}
> > +
> > +/* Core clock mux control */
> > +
> > +/**
> > + * sifive_prci_coreclksel_use_hfclk() - switch the CORECLK mux to output HFCLK
> > + * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
> > + *
> > + * Switch the CORECLK mux to the HFCLK input source; return once complete.
> > + *
> > + * Context: Any context. Caller must prevent concurrent changes to the
> > + * PRCI_CORECLKSEL_OFFSET register.
> > + */
> > +void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd)
> > +{
> > + u32 r;
> > +
> > + r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
> > + r |= PRCI_CORECLKSEL_CORECLKSEL_MASK;
> > + __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
> > +
> > + r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
> > +}
> > +
> > +/**
> > + * sifive_prci_coreclksel_use_corepll() - switch the CORECLK mux to output COREPLL
> > + * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
> > + *
> > + * Switch the CORECLK mux to the PLL output clock; return once complete.
> > + *
> > + * Context: Any context. Caller must prevent concurrent changes to the
> > + * PRCI_CORECLKSEL_OFFSET register.
> > + */
> > +void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd)
> > +{
> > + u32 r;
> > +
> > + r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
> > + r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
> > + __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
> > +
> > + r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
> > +}
> > +
> > +static ulong sifive_prci_parent_rate(struct __prci_clock *pc, struct prci_clk_desc *data)
> > +{
> > + ulong parent_rate;
> > + ulong i;
> > + struct __prci_clock *p;
> > +
> > + if (strcmp(pc->parent_name, "corepll") == 0 ||
> > + strcmp(pc->parent_name, "hfpclkpll") == 0) {
> > + for (i = 0; i < data->num_clks; i++) {
> > + if (strcmp(pc->parent_name, data->clks[i].name) == 0)
> > + break;
> > + }
> > +
> > + if (i >= data->num_clks)
> > + return -ENXIO;
> > +
> > + p = &data->clks[i];
> > + if (!p->pd || !p->ops->recalc_rate)
> > + return -ENXIO;
> > +
> > + return p->ops->recalc_rate(p, sifive_prci_parent_rate(p, data));
> > + }
> > +
> > + if (strcmp(pc->parent_name, "rtcclk") == 0)
> > + parent_rate = clk_get_rate(&pc->pd->parent_rtcclk);
> > + else
> > + parent_rate = clk_get_rate(&pc->pd->parent_hfclk);
> > +
> > + return parent_rate;
> > +}
> > +
> > +static ulong sifive_prci_get_rate(struct clk *clk)
> > +{
> > + struct __prci_clock *pc;
> > + struct prci_clk_desc *data =
> > + (struct prci_clk_desc *)dev_get_driver_data(clk->dev);
> > +
> > + if (data->num_clks <= clk->id)
> > + return -ENXIO;
> > +
> > + pc = &data->clks[clk->id];
> > + if (!pc->pd || !pc->ops->recalc_rate)
> > + return -ENXIO;
> > +
> > + return pc->ops->recalc_rate(pc, sifive_prci_parent_rate(pc, data));
> > +}
> > +
> > +static ulong sifive_prci_set_rate(struct clk *clk, ulong rate)
> > +{
> > + int err;
> > + struct __prci_clock *pc;
> > + struct prci_clk_desc *data =
> > + (struct prci_clk_desc *)dev_get_driver_data(clk->dev);
> > +
> > + if (data->num_clks <= clk->id)
> > + return -ENXIO;
> > +
> > + pc = &data->clks[clk->id];
> > + if (!pc->pd || !pc->ops->set_rate)
> > + return -ENXIO;
> > +
> > + err = pc->ops->set_rate(pc, rate, sifive_prci_parent_rate(pc, data));
> > + if (err)
> > + return err;
> > +
> > + return rate;
> > +}
> > +
> > +static int sifive_prci_enable(struct clk *clk)
> > +{
> > + struct __prci_clock *pc;
> > + int ret = 0;
> > + struct prci_clk_desc *data =
> > + (struct prci_clk_desc *)dev_get_driver_data(clk->dev);
> > +
> > + if (data->num_clks <= clk->id)
> > + return -ENXIO;
> > +
> > + pc = &data->clks[clk->id];
> > + if (!pc->pd)
> > + return -ENXIO;
> > +
> > + if (pc->ops->enable_clk)
> > + ret = pc->ops->enable_clk(pc, 1);
> > +
> > + return ret;
> > +}
> > +
> > +static int sifive_prci_disable(struct clk *clk)
> > +{
> > + struct __prci_clock *pc;
> > + int ret = 0;
> > + struct prci_clk_desc *data =
> > + (struct prci_clk_desc *)dev_get_driver_data(clk->dev);
> > +
> > + if (data->num_clks <= clk->id)
> > + return -ENXIO;
> > +
> > + pc = &data->clks[clk->id];
> > + if (!pc->pd)
> > + return -ENXIO;
> > +
> > + if (pc->ops->enable_clk)
> > + ret = pc->ops->enable_clk(pc, 0);
> > +
> > + return ret;
> > +}
> > +
> > +static int sifive_prci_probe(struct udevice *dev)
> > +{
> > + int i, err;
> > + struct __prci_clock *pc;
> > + struct __prci_data *pd = dev_get_priv(dev);
> > +
> > + struct prci_clk_desc *data =
> > + (struct prci_clk_desc *)dev_get_driver_data(dev);
> > +
> > + pd->va = (void *)dev_read_addr(dev);
> > + if (IS_ERR(pd->va))
> > + return PTR_ERR(pd->va);
> > +
> > + err = clk_get_by_index(dev, 0, &pd->parent_hfclk);
> > + if (err)
> > + return err;
> > +
> > + err = clk_get_by_index(dev, 1, &pd->parent_rtcclk);
> > + if (err)
> > + return err;
> > +
> > + for (i = 0; i < data->num_clks; ++i) {
> > + pc = &data->clks[i];
> > + pc->pd = pd;
> > + if (pc->pwd)
> > + __prci_wrpll_read_cfg0(pd, pc->pwd);
> > + }
> > +
> > + if (IS_ENABLED(CONFIG_SPL_BUILD)) {
> > + if (device_is_compatible(dev, "sifive,fu740-c000-prci")) {
> > + u32 prci_pll_reg;
> > + unsigned long parent_rate;
> > +
> > + prci_pll_reg = readl(pd->va + PRCI_PRCIPLL_OFFSET);
> > +
> > + if (prci_pll_reg & PRCI_PRCIPLL_HFPCLKPLL) {
> > + /*
> > + * Only initialize the HFPCLK PLL. In this
> > + * case the design uses hfpclk to drive
> > + * Chiplink
> > + */
> > + pc = &data->clks[PRCI_CLK_HFPCLKPLL];
> > + parent_rate = sifive_prci_parent_rate(pc, data);
> > + sifive_prci_wrpll_set_rate(pc, 260000000,
> > + parent_rate);
> > + pc->ops->enable_clk(pc, 1);
> > + } else if (prci_pll_reg & PRCI_PRCIPLL_CLTXPLL) {
> > + /* CLTX pll init */
> > + pc = &data->clks[PRCI_CLK_CLTXPLL];
> > + parent_rate = sifive_prci_parent_rate(pc, data);
> > + sifive_prci_wrpll_set_rate(pc, 260000000,
> > + parent_rate);
> > + pc->ops->enable_clk(pc, 1);
> > + }
> > + }
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static struct clk_ops sifive_prci_ops = {
> > + .set_rate = sifive_prci_set_rate,
> > + .get_rate = sifive_prci_get_rate,
> > + .enable = sifive_prci_enable,
> > + .disable = sifive_prci_disable,
> > +};
> > +
> > +static int sifive_clk_bind(struct udevice *dev)
> > +{
> > + return sifive_reset_bind(dev, PRCI_DEVICERESETCNT);
> > +}
> > +
> > +static const struct udevice_id sifive_prci_ids[] = {
> > + { .compatible = "sifive,fu540-c000-prci", .data = (ulong)&prci_clk_fu540 },
> > + { .compatible = "sifive,fu740-c000-prci", .data = (ulong)&prci_clk_fu740 },
> > + { }
> > +};
> > +
> > +U_BOOT_DRIVER(sifive_prci) = {
> > + .name = "sifive-prci",
> > + .id = UCLASS_CLK,
> > + .of_match = sifive_prci_ids,
> > + .probe = sifive_prci_probe,
> > + .ops = &sifive_prci_ops,
> > + .priv_auto = sizeof(struct __prci_data),
> > + .bind = sifive_clk_bind,
> > +};
> > diff --git a/drivers/clk/sifive/sifive-prci.h b/drivers/clk/sifive/sifive-prci.h
> > new file mode 100644
> > index 0000000000..5ce33d6184
> > --- /dev/null
> > +++ b/drivers/clk/sifive/sifive-prci.h
> > @@ -0,0 +1,323 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (C) 2020-2021 SiFive, Inc.
> > + * Wesley Terpstra
> > + * Paul Walmsley
> > + * Zong Li
> > + * Pragnesh Patel
> > + */
> > +
> > +#ifndef __SIFIVE_CLK_SIFIVE_PRCI_H
> > +#define __SIFIVE_CLK_SIFIVE_PRCI_H
> > +
> > +#include <clk.h>
> > +#include <linux/clk/analogbits-wrpll-cln28hpc.h>
> > +
> > +/*
> > + * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
> > + * hfclk and rtcclk
> > + */
> > +#define EXPECTED_CLK_PARENT_COUNT 2
> > +
> > +/*
> > + * Register offsets and bitmasks
> > + */
> > +
> > +/* COREPLLCFG0 */
> > +#define PRCI_COREPLLCFG0_OFFSET 0x4
> > +#define PRCI_COREPLLCFG0_DIVR_SHIFT 0
> > +#define PRCI_COREPLLCFG0_DIVR_MASK (0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT)
> > +#define PRCI_COREPLLCFG0_DIVF_SHIFT 6
> > +#define PRCI_COREPLLCFG0_DIVF_MASK (0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT)
> > +#define PRCI_COREPLLCFG0_DIVQ_SHIFT 15
> > +#define PRCI_COREPLLCFG0_DIVQ_MASK (0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT)
> > +#define PRCI_COREPLLCFG0_RANGE_SHIFT 18
> > +#define PRCI_COREPLLCFG0_RANGE_MASK (0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT)
> > +#define PRCI_COREPLLCFG0_BYPASS_SHIFT 24
> > +#define PRCI_COREPLLCFG0_BYPASS_MASK (0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT)
> > +#define PRCI_COREPLLCFG0_FSE_SHIFT 25
> > +#define PRCI_COREPLLCFG0_FSE_MASK (0x1 << PRCI_COREPLLCFG0_FSE_SHIFT)
> > +#define PRCI_COREPLLCFG0_LOCK_SHIFT 31
> > +#define PRCI_COREPLLCFG0_LOCK_MASK (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
> > +
> > +/* COREPLLCFG1 */
> > +#define PRCI_COREPLLCFG1_OFFSET 0x8
> > +#define PRCI_COREPLLCFG1_CKE_SHIFT 31
> > +#define PRCI_COREPLLCFG1_CKE_MASK (0x1 << PRCI_COREPLLCFG1_CKE_SHIFT)
> > +
> > +/* DDRPLLCFG0 */
> > +#define PRCI_DDRPLLCFG0_OFFSET 0xc
> > +#define PRCI_DDRPLLCFG0_DIVR_SHIFT 0
> > +#define PRCI_DDRPLLCFG0_DIVR_MASK (0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT)
> > +#define PRCI_DDRPLLCFG0_DIVF_SHIFT 6
> > +#define PRCI_DDRPLLCFG0_DIVF_MASK (0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT)
> > +#define PRCI_DDRPLLCFG0_DIVQ_SHIFT 15
> > +#define PRCI_DDRPLLCFG0_DIVQ_MASK (0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT)
> > +#define PRCI_DDRPLLCFG0_RANGE_SHIFT 18
> > +#define PRCI_DDRPLLCFG0_RANGE_MASK (0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT)
> > +#define PRCI_DDRPLLCFG0_BYPASS_SHIFT 24
> > +#define PRCI_DDRPLLCFG0_BYPASS_MASK (0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT)
> > +#define PRCI_DDRPLLCFG0_FSE_SHIFT 25
> > +#define PRCI_DDRPLLCFG0_FSE_MASK (0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT)
> > +#define PRCI_DDRPLLCFG0_LOCK_SHIFT 31
> > +#define PRCI_DDRPLLCFG0_LOCK_MASK (0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT)
> > +
> > +/* DDRPLLCFG1 */
> > +#define PRCI_DDRPLLCFG1_OFFSET 0x10
> > +#define PRCI_DDRPLLCFG1_CKE_SHIFT 31
> > +#define PRCI_DDRPLLCFG1_CKE_MASK (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
> > +
> > +/* PCIEAUXCFG1 */
> > +#define PRCI_PCIEAUXCFG1_OFFSET 0x14
> > +#define PRCI_PCIEAUXCFG1_SHIFT 0
> > +#define PRCI_PCIEAUXCFG1_MASK (0x1 << PRCI_PCIEAUXCFG1_SHIFT)
> > +
> > +/* GEMGXLPLLCFG0 */
> > +#define PRCI_GEMGXLPLLCFG0_OFFSET 0x1c
> > +#define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT 0
> > +#define PRCI_GEMGXLPLLCFG0_DIVR_MASK \
> > + (0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT)
> > +#define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT 6
> > +#define PRCI_GEMGXLPLLCFG0_DIVF_MASK \
> > + (0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT)
> > +#define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT 15
> > +#define PRCI_GEMGXLPLLCFG0_DIVQ_MASK (0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT)
> > +#define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT 18
> > +#define PRCI_GEMGXLPLLCFG0_RANGE_MASK \
> > + (0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT)
> > +#define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT 24
> > +#define PRCI_GEMGXLPLLCFG0_BYPASS_MASK \
> > + (0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT)
> > +#define PRCI_GEMGXLPLLCFG0_FSE_SHIFT 25
> > +#define PRCI_GEMGXLPLLCFG0_FSE_MASK \
> > + (0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT)
> > +#define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT 31
> > +#define PRCI_GEMGXLPLLCFG0_LOCK_MASK (0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT)
> > +
> > +/* GEMGXLPLLCFG1 */
> > +#define PRCI_GEMGXLPLLCFG1_OFFSET 0x20
> > +#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT 31
> > +#define PRCI_GEMGXLPLLCFG1_CKE_MASK (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
> > +
> > +/* CORECLKSEL */
> > +#define PRCI_CORECLKSEL_OFFSET 0x24
> > +#define PRCI_CORECLKSEL_CORECLKSEL_SHIFT 0
> > +#define PRCI_CORECLKSEL_CORECLKSEL_MASK \
> > + (0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT)
> > +
> > +/* DEVICESRESETREG */
> > +#define PRCI_DEVICESRESETREG_OFFSET 0x28
> > +#define PRCI_DEVICERESETCNT 6
> > +
> > +/* CLKMUXSTATUSREG */
> > +#define PRCI_CLKMUXSTATUSREG_OFFSET 0x2c
> > +#define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT 1
> > +#define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \
> > + (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
> > +
> > +/* CLTXPLLCFG0 */
> > +#define PRCI_CLTXPLLCFG0_OFFSET 0x30
> > +#define PRCI_CLTXPLLCFG0_DIVR_SHIFT 0
> > +#define PRCI_CLTXPLLCFG0_DIVR_MASK (0x3f << PRCI_CLTXPLLCFG0_DIVR_SHIFT)
> > +#define PRCI_CLTXPLLCFG0_DIVF_SHIFT 6
> > +#define PRCI_CLTXPLLCFG0_DIVF_MASK (0x1ff << PRCI_CLTXPLLCFG0_DIVF_SHIFT)
> > +#define PRCI_CLTXPLLCFG0_DIVQ_SHIFT 15
> > +#define PRCI_CLTXPLLCFG0_DIVQ_MASK (0x7 << PRCI_CLTXPLLCFG0_DIVQ_SHIFT)
> > +#define PRCI_CLTXPLLCFG0_RANGE_SHIFT 18
> > +#define PRCI_CLTXPLLCFG0_RANGE_MASK (0x7 << PRCI_CLTXPLLCFG0_RANGE_SHIFT)
> > +#define PRCI_CLTXPLLCFG0_BYPASS_SHIFT 24
> > +#define PRCI_CLTXPLLCFG0_BYPASS_MASK (0x1 << PRCI_CLTXPLLCFG0_BYPASS_SHIFT)
> > +#define PRCI_CLTXPLLCFG0_FSE_SHIFT 25
> > +#define PRCI_CLTXPLLCFG0_FSE_MASK (0x1 << PRCI_CLTXPLLCFG0_FSE_SHIFT)
> > +#define PRCI_CLTXPLLCFG0_LOCK_SHIFT 31
> > +#define PRCI_CLTXPLLCFG0_LOCK_MASK (0x1 << PRCI_CLTXPLLCFG0_LOCK_SHIFT)
> > +
> > +/* CLTXPLLCFG1 */
> > +#define PRCI_CLTXPLLCFG1_OFFSET 0x34
> > +#define PRCI_CLTXPLLCFG1_CKE_SHIFT 24
> > +#define PRCI_CLTXPLLCFG1_CKE_MASK (0x1 << PRCI_CLTXPLLCFG1_CKE_SHIFT)
> > +
> > +/* DVFSCOREPLLCFG0 */
> > +#define PRCI_DVFSCOREPLLCFG0_OFFSET 0x38
> > +
> > +/* DVFSCOREPLLCFG1 */
> > +#define PRCI_DVFSCOREPLLCFG1_OFFSET 0x3c
> > +#define PRCI_DVFSCOREPLLCFG1_CKE_SHIFT 24
> > +#define PRCI_DVFSCOREPLLCFG1_CKE_MASK (0x1 << PRCI_DVFSCOREPLLCFG1_CKE_SHIFT)
> > +
> > +/* COREPLLSEL */
> > +#define PRCI_COREPLLSEL_OFFSET 0x40
> > +#define PRCI_COREPLLSEL_COREPLLSEL_SHIFT 0
> > +#define PRCI_COREPLLSEL_COREPLLSEL_MASK \
> > + (0x1 << PRCI_COREPLLSEL_COREPLLSEL_SHIFT)
> > +
> > +/* HFPCLKPLLCFG0 */
> > +#define PRCI_HFPCLKPLLCFG0_OFFSET 0x50
> > +#define PRCI_HFPCLKPLL_CFG0_DIVR_SHIFT 0
> > +#define PRCI_HFPCLKPLL_CFG0_DIVR_MASK \
> > + (0x3f << PRCI_HFPCLKPLLCFG0_DIVR_SHIFT)
> > +#define PRCI_HFPCLKPLL_CFG0_DIVF_SHIFT 6
> > +#define PRCI_HFPCLKPLL_CFG0_DIVF_MASK \
> > + (0x1ff << PRCI_HFPCLKPLLCFG0_DIVF_SHIFT)
> > +#define PRCI_HFPCLKPLL_CFG0_DIVQ_SHIFT 15
> > +#define PRCI_HFPCLKPLL_CFG0_DIVQ_MASK \
> > + (0x7 << PRCI_HFPCLKPLLCFG0_DIVQ_SHIFT)
> > +#define PRCI_HFPCLKPLL_CFG0_RANGE_SHIFT 18
> > +#define PRCI_HFPCLKPLL_CFG0_RANGE_MASK \
> > + (0x7 << PRCI_HFPCLKPLLCFG0_RANGE_SHIFT)
> > +#define PRCI_HFPCLKPLL_CFG0_BYPASS_SHIFT 24
> > +#define PRCI_HFPCLKPLL_CFG0_BYPASS_MASK \
> > + (0x1 << PRCI_HFPCLKPLLCFG0_BYPASS_SHIFT)
> > +#define PRCI_HFPCLKPLL_CFG0_FSE_SHIFT 25
> > +#define PRCI_HFPCLKPLL_CFG0_FSE_MASK \
> > + (0x1 << PRCI_HFPCLKPLLCFG0_FSE_SHIFT)
> > +#define PRCI_HFPCLKPLL_CFG0_LOCK_SHIFT 31
> > +#define PRCI_HFPCLKPLL_CFG0_LOCK_MASK \
> > + (0x1 << PRCI_HFPCLKPLLCFG0_LOCK_SHIFT)
> > +
> > +/* HFPCLKPLLCFG1 */
> > +#define PRCI_HFPCLKPLLCFG1_OFFSET 0x54
> > +#define PRCI_HFPCLKPLLCFG1_CKE_SHIFT 24
> > +#define PRCI_HFPCLKPLLCFG1_CKE_MASK \
> > + (0x1 << PRCI_HFPCLKPLLCFG1_CKE_SHIFT)
> > +
> > +/* HFPCLKPLLSEL */
> > +#define PRCI_HFPCLKPLLSEL_OFFSET 0x58
> > +#define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT 0
> > +#define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK \
> > + (0x1 << PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT)
> > +
> > +/* HFPCLKPLLDIV */
> > +#define PRCI_HFPCLKPLLDIV_OFFSET 0x5c
> > +
> > +/* PRCIPLL */
> > +#define PRCI_PRCIPLL_OFFSET 0xe0
> > +
> > +#define PRCI_PRCIPLL_CLTXPLL (0x1 << 0)
> > +#define PRCI_PRCIPLL_GEMGXLPLL (0x1 << 1)
> > +#define PRCI_PRCIPLL_DDRPLL (0x1 << 2)
> > +#define PRCI_PRCIPLL_HFPCLKPLL (0x1 << 3)
> > +#define PRCI_PRCIPLL_DVFSCOREPLL (0x1 << 4)
> > +#define PRCI_PRCIPLL_COREPLL (0x1 << 5)
> > +
> > +/* PROCMONCFG */
> > +#define PRCI_PROCMONCFG_OFFSET 0xF0
> > +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24
> > +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
> > + (0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
> > +
> > +/*
> > + * Private structures
> > + */
> > +
> > +/**
> > + * struct __prci_data - per-device-instance data
> > + * @va: base virtual address of the PRCI IP block
> > + * @parent: parent clk instance
> > + *
> > + * PRCI per-device instance data
> > + */
> > +struct __prci_data {
> > + void *va;
> > + struct clk parent_hfclk;
> > + struct clk parent_rtcclk;
> > +};
> > +
> > +/**
> > + * struct __prci_wrpll_data - WRPLL configuration and integration data
> > + * @c: WRPLL current configuration record
> > + * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
> > + * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
> > + * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
> > + * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address
> > + * @release_reset: fn ptr to code to release clock reset
> > + *
> > + * @enable_bypass and @disable_bypass are used for WRPLL instances
> > + * that contain a separate external glitchless clock mux downstream
> > + * from the PLL. The WRPLL internal bypass mux is not glitchless.
> > + */
> > +struct __prci_wrpll_data {
> > + struct wrpll_cfg c;
> > + void (*enable_bypass)(struct __prci_data *pd);
> > + void (*disable_bypass)(struct __prci_data *pd);
> > + u8 cfg0_offs;
> > + u8 cfg1_offs;
> > + void (*release_reset)(struct __prci_data *pd);
> > +};
> > +
> > +/**
> > + * struct __prci_clock - describes a clock device managed by PRCI
> > + * @name: user-readable clock name string - should match the manual
> > + * @parent_name: parent name for this clock
> > + * @ops: struct __prci_clock_ops for control
> > + * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
> > + * @pd: PRCI-specific data associated with this clock (if not NULL)
> > + *
> > + * PRCI clock data. Used by the PRCI driver to register PRCI-provided
> > + * clocks to the Linux clock infrastructure.
> > + */
> > +struct __prci_clock {
> > + const char *name;
> > + const char *parent_name;
> > + const struct __prci_clock_ops *ops;
> > + struct __prci_wrpll_data *pwd;
> > + struct __prci_data *pd;
> > +};
> > +
> > +/* struct __prci_clock_ops - clock operations */
> > +struct __prci_clock_ops {
> > + int (*set_rate)(struct __prci_clock *pc,
> > + unsigned long rate,
> > + unsigned long parent_rate);
> > + unsigned long (*round_rate)(struct __prci_clock *pc,
> > + unsigned long rate,
> > + unsigned long *parent_rate);
> > + unsigned long (*recalc_rate)(struct __prci_clock *pc,
> > + unsigned long parent_rate);
> > + int (*enable_clk)(struct __prci_clock *pc, bool enable);
> > +};
> > +
> > +/*
> > + * struct prci_clk_desc - describes the information of clocks of each SoCs
> > + * @clks: point to a array of __prci_clock
> > + * @num_clks: the number of element of clks
> > + */
> > +struct prci_clk_desc {
> > + struct __prci_clock *clks;
> > + size_t num_clks;
> > +};
> > +
> > +void sifive_prci_ethernet_release_reset(struct __prci_data *pd);
> > +void sifive_prci_ddr_release_reset(struct __prci_data *pd);
> > +void sifive_prci_cltx_release_reset(struct __prci_data *pd);
> > +
> > +/* Core clock mux control */
> > +void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd);
> > +void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd);
> > +void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd);
> > +void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd);
> > +void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd);
> > +void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd);
> > +void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd);
> > +
> > +unsigned long sifive_prci_wrpll_round_rate(struct __prci_clock *pc,
> > + unsigned long rate,
> > + unsigned long *parent_rate);
> > +
> > +/* Linux clock framework integration */
> > +int sifive_prci_wrpll_set_rate(struct __prci_clock *pc,
> > + unsigned long rate,
> > + unsigned long parent_rate);
> > +
> > +unsigned long sifive_prci_wrpll_recalc_rate(struct __prci_clock *pc,
> > + unsigned long parent_rate);
> > +
> > +unsigned long sifive_prci_tlclksel_recalc_rate(struct __prci_clock *pc,
> > + unsigned long parent_rate);
> > +
> > +unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct __prci_clock *pc,
> > + unsigned long parent_rate);
> > +
> > +int sifive_prci_clock_enable(struct __prci_clock *pc, bool enable);
> > +
> > +#endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */
> > --
> > 2.31.0
> >
>
>
> --
> Regards,
>
> Dimitri.
1
0
The patchset is to upstream NXP downstream network patches that
runs on i.MX platforms, including eqos update, sharded mdio support,
mac addr accessing and etc.
Fugang Duan (3):
net: phy: realtek: add rx delay support for RTL8211F
net: dwc_eth_qos: add dwc eqos for imx support
net: eqos: implement callbaks to get interface and set txclk rate
Peng Fan (1):
net: eth-uclass: add return value check
Ye Li (4):
net: Add eth phy generic driver for shared MDIO
net: Update eQos driver and FEC driver to use eth phy interfaces
fec: Move imx_get_mac_from_fuse declare to imx file
eQos: Implement the read_rom_hwaddr callback
arch/arm/include/asm/mach-imx/sys_proto.h | 2 +
drivers/net/Kconfig | 6 +
drivers/net/Makefile | 1 +
drivers/net/dwc_eth_qos.c | 284 +++++++++++++++++++++++++++---
drivers/net/eth-phy-uclass.c | 123 +++++++++++++
drivers/net/fec_mxc.c | 16 +-
drivers/net/fec_mxc.h | 2 -
drivers/net/phy/realtek.c | 11 ++
include/dm/uclass-id.h | 1 +
include/eth_phy.h | 17 ++
net/eth-uclass.c | 17 +-
11 files changed, 446 insertions(+), 34 deletions(-)
create mode 100644 drivers/net/eth-phy-uclass.c
create mode 100644 include/eth_phy.h
--
2.16.4
2
9