Xilinx changes for v2022.10
cpu: - Add driver for microblaze cpu net: - Add support for DM_ETH_PHY to AXI emac and emaclite xilinx: - Switch platforms to DM_ETH_PHY - DT chagnes in ZynqMP and Zynq - Enable support for SquashFS zynqmp: - Add support for KR260 boards - Move BSS from address 0 - Move platform identification from board code to soc driver - Improve zynqmp_psu_init_minimize versal: - Enable loading app at EL1 serial: - Setup default address and clock rates for DEBUG uarts pinctrl: - Add support for tri state and output enable properties relocate-rela: - Clean relocate-rela implementation for ARM64 - Add support for Microblaze microblaze: - Add support for runtime relocation - Rework cache handling (wiring, Kconfig) based on cpuinfo - Remove interrupt support timer: - Extract axi timer driver from Microblaze to generic location -----BEGIN PGP SIGNATURE----- iF0EABECAB0WIQQbPNTMvXmYlBPRwx7KSWXLKUoMIQUCYrlYngAKCRDKSWXLKUoM ITgbAJ9S9xO2QqxtuodWAYMtJfvZ14c7mgCeKnyFTrrBnJkC0wPsGqE71oNJ49o= =3gGm -----END PGP SIGNATURE----- Merge tag 'xilinx-for-v2022.10' of https://source.denx.de/u-boot/custodians/u-boot-microblaze into next Xilinx changes for v2022.10 cpu: - Add driver for microblaze cpu net: - Add support for DM_ETH_PHY to AXI emac and emaclite xilinx: - Switch platforms to DM_ETH_PHY - DT chagnes in ZynqMP and Zynq - Enable support for SquashFS zynqmp: - Add support for KR260 boards - Move BSS from address 0 - Move platform identification from board code to soc driver - Improve zynqmp_psu_init_minimize versal: - Enable loading app at EL1 serial: - Setup default address and clock rates for DEBUG uarts pinctrl: - Add support for tri state and output enable properties relocate-rela: - Clean relocate-rela implementation for ARM64 - Add support for Microblaze microblaze: - Add support for runtime relocation - Rework cache handling (wiring, Kconfig) based on cpuinfo - Remove interrupt support timer: - Extract axi timer driver from Microblaze to generic location
This commit is contained in:
commit
c316ee674f
|
@ -1004,6 +1004,7 @@ F: drivers/net/xilinx_emaclite.c
|
|||
F: drivers/serial/serial_xuartlite.c
|
||||
F: drivers/spi/xilinx_spi.c
|
||||
F: drivers/sysreset/sysreset_gpio.c
|
||||
F: drivers/timer/xilinx-timer.c
|
||||
F: drivers/watchdog/xilinx_tb_wdt.c
|
||||
N: xilinx
|
||||
|
||||
|
|
6
Makefile
6
Makefile
|
@ -922,12 +922,10 @@ endif
|
|||
# the raw binary, but certain simulators only accept an ELF file (but don't
|
||||
# do the relocation).
|
||||
ifneq ($(CONFIG_STATIC_RELA),)
|
||||
# $(1) is u-boot ELF, $(2) is u-boot bin, $(3) is text base
|
||||
# $(2) is u-boot ELF, $(3) is u-boot bin, $(4) is text base
|
||||
quiet_cmd_static_rela = RELOC $@
|
||||
cmd_static_rela = \
|
||||
start=$$($(NM) $(2) | grep __rel_dyn_start | cut -f 1 -d ' '); \
|
||||
end=$$($(NM) $(2) | grep __rel_dyn_end | cut -f 1 -d ' '); \
|
||||
tools/relocate-rela $(3) $(4) $$start $$end
|
||||
tools/relocate-rela $(3) $(2)
|
||||
else
|
||||
quiet_cmd_static_rela =
|
||||
cmd_static_rela =
|
||||
|
|
32
arch/Kconfig
32
arch/Kconfig
|
@ -8,9 +8,6 @@ config CREATE_ARCH_SYMLINK
|
|||
config HAVE_ARCH_IOREMAP
|
||||
bool
|
||||
|
||||
config NEEDS_MANUAL_RELOC
|
||||
bool
|
||||
|
||||
config SYS_CACHE_SHIFT_4
|
||||
bool
|
||||
|
||||
|
@ -76,9 +73,12 @@ config M68K
|
|||
|
||||
config MICROBLAZE
|
||||
bool "MicroBlaze architecture"
|
||||
select NEEDS_MANUAL_RELOC
|
||||
select SUPPORT_OF_CONTROL
|
||||
imply CMD_IRQ
|
||||
imply CMD_TIMER
|
||||
imply SPL_REGMAP if SPL
|
||||
imply SPL_TIMER if SPL
|
||||
imply TIMER
|
||||
imply XILINX_TIMER
|
||||
|
||||
config MIPS
|
||||
bool "MIPS architecture"
|
||||
|
@ -452,3 +452,25 @@ source "arch/xtensa/Kconfig"
|
|||
source "arch/riscv/Kconfig"
|
||||
|
||||
source "board/keymile/Kconfig"
|
||||
|
||||
if MIPS || MICROBLAZE
|
||||
|
||||
choice
|
||||
prompt "Endianness selection"
|
||||
help
|
||||
Some MIPS boards can be configured for either little or big endian
|
||||
byte order. These modes require different U-Boot images. In general there
|
||||
is one preferred byteorder for a particular system but some systems are
|
||||
just as commonly used in the one or the other endianness.
|
||||
|
||||
config SYS_BIG_ENDIAN
|
||||
bool "Big endian"
|
||||
depends on (SUPPORTS_BIG_ENDIAN && MIPS) || MICROBLAZE
|
||||
|
||||
config SYS_LITTLE_ENDIAN
|
||||
bool "Little endian"
|
||||
depends on (SUPPORTS_LITTLE_ENDIAN && MIPS) || MICROBLAZE
|
||||
|
||||
endchoice
|
||||
|
||||
endif
|
||||
|
|
|
@ -342,6 +342,8 @@ dtb-$(CONFIG_ARCH_ZYNQMP) += \
|
|||
zynqmp-mini-qspi.dtb \
|
||||
zynqmp-sm-k26-revA.dtb \
|
||||
zynqmp-smk-k26-revA.dtb \
|
||||
zynqmp-sck-kr-g-revA.dtbo \
|
||||
zynqmp-sck-kr-g-revB.dtbo \
|
||||
zynqmp-sck-kv-g-revA.dtbo \
|
||||
zynqmp-sck-kv-g-revB.dtbo \
|
||||
zynqmp-topic-miamimp-xilinx-xdp-v1r1.dtb \
|
||||
|
|
|
@ -287,7 +287,7 @@
|
|||
reg = <0 0 0x1000000>;
|
||||
status = "disabled";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
nor0: flash@1,0 {
|
||||
status = "disabled";
|
||||
|
|
|
@ -294,10 +294,10 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <2>;
|
||||
clock_8t49n287: clock-generator@d8 { /* u39 8T49N240 */
|
||||
clock_8t49n287: clock-generator@6c { /* u39 8T49N240 */
|
||||
#clock-cells = <1>; /* author David Cater <david.cater@idt.com>*/
|
||||
compatible = "idt,8t49n240", "idt,8t49n241"; /* FIXME no driver for 240 */
|
||||
reg = <0xd8>;
|
||||
reg = <0x6c>;
|
||||
/* Documentation/devicetree/bindings/clock/idt,idt8t49n24x.txt */
|
||||
/* FIXME there input via J241 Samtec CLK1 and CLK0 from U38 - selection PIN */
|
||||
};
|
||||
|
@ -447,7 +447,7 @@
|
|||
si570_user1: clock-generator@5d { /* u205 */
|
||||
#clock-cells = <0>;
|
||||
compatible = "silabs,si570";
|
||||
reg = <0x5f>;
|
||||
reg = <0x5d>;
|
||||
temperature-stability = <50>;
|
||||
factory-fout = <100000000>;
|
||||
clock-frequency = <100000000>;
|
||||
|
|
|
@ -260,9 +260,9 @@
|
|||
reg = <0x45>;
|
||||
shunt-resistor = <5000>;
|
||||
};
|
||||
tps53681@c0 { /* u53 - FIXME name - don't know what it does - also vcc_io_soc */
|
||||
tps53681@60 { /* u53 - 0xc0 - FIXME name - don't know what it does - also vcc_io_soc */
|
||||
compatible = "ti,tps53681", "ti,tps53679";
|
||||
reg = <0xc0>;
|
||||
reg = <0x60>;
|
||||
};
|
||||
};
|
||||
i2c@3 { /* fmc1 via JA2G */
|
||||
|
|
|
@ -247,9 +247,9 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <2>;
|
||||
reg_vccint: tps53681@c0 { /* u69 */
|
||||
reg_vccint: tps53681@60 { /* u69 - 0xc0 */
|
||||
compatible = "ti,tps53681", "ti,tps53679";
|
||||
reg = <0xc0>;
|
||||
reg = <0x60>;
|
||||
};
|
||||
reg_vcc_pmc: tps544@7 { /* u80 */
|
||||
compatible = "ti,tps544b25";
|
||||
|
|
|
@ -190,10 +190,6 @@
|
|||
compatible = "ti,tps544b25";
|
||||
reg = <0x1e>;
|
||||
};
|
||||
reg_vpp_2v5_ddr4: tps544@1x { /* u3007 */
|
||||
compatible = "ti,tps544b25";
|
||||
reg = <0x17>; /* FIXME wrong in schematics */
|
||||
};
|
||||
};
|
||||
i2c@1 { /* PMBUS_INA226 */
|
||||
#address-cells = <1>;
|
||||
|
@ -239,9 +235,9 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <2>;
|
||||
reg_vccint: tps53681@c0 { /* u69 */
|
||||
reg_vccint: tps53681@60 { /* u69 - 0xc0 */
|
||||
compatible = "ti,tps53681", "ti,tps53679";
|
||||
reg = <0xc0>;
|
||||
reg = <0x60>;
|
||||
};
|
||||
reg_vcc_pmc: tps544@7 { /* u80 */
|
||||
compatible = "ti,tps544b25";
|
||||
|
|
|
@ -190,9 +190,9 @@
|
|||
compatible = "ti,tps544b25";
|
||||
reg = <0x1e>;
|
||||
};
|
||||
reg_vpp_2v5_ddr4: tps544@1x { /* u3007 */
|
||||
reg_vcc1v2_ddr4: tps544@18 { /* u3022 */
|
||||
compatible = "ti,tps544b25";
|
||||
reg = <0x17>; /* FIXME wrong in schematics */
|
||||
reg = <0x18>;
|
||||
};
|
||||
};
|
||||
i2c@1 { /* PMBUS_INA226 */
|
||||
|
@ -239,9 +239,9 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <2>;
|
||||
reg_vccint: tps53681@c0 { /* u69 */
|
||||
reg_vccint: tps53681@60 { /* u69 - 0xc0 */
|
||||
compatible = "ti,tps53681", "ti,tps53679";
|
||||
reg = <0xc0>;
|
||||
reg = <0x60>;
|
||||
};
|
||||
reg_vcc_pmc: tps544@7 { /* u80 */
|
||||
compatible = "ti,tps544b25";
|
||||
|
|
388
arch/arm/dts/zynqmp-sck-kr-g-revA.dts
Normal file
388
arch/arm/dts/zynqmp-sck-kr-g-revA.dts
Normal file
|
@ -0,0 +1,388 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* dts file for KR260 revA Carrier Card
|
||||
*
|
||||
* (C) Copyright 2021, Xilinx, Inc.
|
||||
*
|
||||
* Michal Simek <michal.simek@xilinx.com>
|
||||
*/
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/net/ti-dp83867.h>
|
||||
#include <dt-bindings/phy/phy.h>
|
||||
#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
&{/} {
|
||||
compatible = "xlnx,zynqmp-sk-kr260-revA",
|
||||
"xlnx,zynqmp-sk-kr260", "xlnx,zynqmp";
|
||||
|
||||
ina260-u14 {
|
||||
compatible = "iio-hwmon";
|
||||
io-channels = <&u14 0>, <&u14 1>, <&u14 2>;
|
||||
};
|
||||
|
||||
si5332_0: si5332_0 { /* u17 - GEM0/1 */
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <125000000>;
|
||||
};
|
||||
|
||||
si5332_1: si5332_1 { /* u17 - DP */
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <27000000>;
|
||||
};
|
||||
|
||||
si5332_2: si5332_2 { /* u17 - USB */
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <26000000>;
|
||||
};
|
||||
|
||||
si5332_3: si5332_3 { /* u17 - SFP+ */
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <156250000>;
|
||||
};
|
||||
|
||||
si5332_4: si5332_4 { /* u17 - GEM2 */
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <25000000>;
|
||||
};
|
||||
|
||||
si5332_5: si5332_5 { /* u17 - GEM3 */
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <25000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c1 { /* I2C_SCK C26/C27 - MIO from SOM */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pinctrl-names = "default", "gpio";
|
||||
pinctrl-0 = <&pinctrl_i2c1_default>;
|
||||
pinctrl-1 = <&pinctrl_i2c1_gpio>;
|
||||
scl-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
|
||||
sda-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
u14: ina260@40 { /* u14 */
|
||||
compatible = "ti,ina260";
|
||||
#io-channel-cells = <1>;
|
||||
label = "ina260-u14";
|
||||
reg = <0x40>;
|
||||
};
|
||||
|
||||
slg7xl45106: gpio@11 { /* u19 - reset logic */
|
||||
compatible = "dlg,slg7xl45106";
|
||||
reg = <0x11>;
|
||||
label = "resetchip";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-line-names = "USB0_PHY_RESET_B", "USB1_PHY_RESET_B",
|
||||
"SD_RESET_B", "USB0_HUB_RESET_B",
|
||||
"USB1_HUB_RESET_B", "PS_GEM0_RESET_B",
|
||||
"PS_GEM1_RESET_B", "";
|
||||
};
|
||||
|
||||
i2c-mux@74 { /* u18 */
|
||||
compatible = "nxp,pca9546";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x74>;
|
||||
usbhub_i2c0: i2c@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
};
|
||||
usbhub_i2c1: i2c@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
};
|
||||
/* Bus 2/3 are not connected */
|
||||
};
|
||||
|
||||
/* si5332@6a - u17 - clock-generator */
|
||||
};
|
||||
|
||||
/* GEM SGMII/DP and USB 3.0 */
|
||||
&psgtr {
|
||||
status = "okay";
|
||||
/* gem0/1, dp, usb */
|
||||
clocks = <&si5332_0>, <&si5332_1>, <&si5332_2>;
|
||||
clock-names = "ref0", "ref1", "ref2";
|
||||
};
|
||||
|
||||
&zynqmp_dpsub {
|
||||
status = "okay";
|
||||
phy-names = "dp-phy0";
|
||||
phys = <&psgtr 1 PHY_TYPE_DP 0 1>;
|
||||
assigned-clock-rates = <27000000>, <25000000>, <300000000>;
|
||||
};
|
||||
|
||||
&zynqmp_dpdma {
|
||||
status = "okay";
|
||||
assigned-clock-rates = <600000000>;
|
||||
};
|
||||
|
||||
&usb0 { /* mio52 - mio63 */
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_usb0_default>;
|
||||
phy-names = "usb3-phy";
|
||||
phys = <&psgtr 2 PHY_TYPE_USB3 0 2>;
|
||||
reset-gpios = <&slg7xl45106 0 GPIO_ACTIVE_LOW>;
|
||||
assigned-clock-rates = <250000000>, <20000000>;
|
||||
|
||||
usbhub0: usb-hub { /* u43 */
|
||||
i2c-bus = <&usbhub_i2c0>;
|
||||
compatible = "microchip,usb5744";
|
||||
reset-gpios = <&slg7xl45106 3 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
usb2244: usb-sd { /* u38 */
|
||||
compatible = "microchip,usb2244";
|
||||
reset-gpios = <&slg7xl45106 2 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
&dwc3_0 {
|
||||
status = "okay";
|
||||
dr_mode = "host";
|
||||
snps,usb3_lpm_capable;
|
||||
maximum-speed = "super-speed";
|
||||
};
|
||||
|
||||
&usb1 { /* mio64 - mio75 */
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_usb1_default>;
|
||||
phy-names = "usb3-phy";
|
||||
phys = <&psgtr 3 PHY_TYPE_USB3 1 2>;
|
||||
reset-gpios = <&slg7xl45106 1 GPIO_ACTIVE_LOW>;
|
||||
assigned-clock-rates = <250000000>, <20000000>;
|
||||
|
||||
usbhub1: usb-hub { /* u84 */
|
||||
i2c-bus = <&usbhub_i2c1>;
|
||||
compatible = "microchip,usb5744";
|
||||
reset-gpios = <&slg7xl45106 4 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
&dwc3_1 {
|
||||
status = "okay";
|
||||
dr_mode = "host";
|
||||
snps,usb3_lpm_capable;
|
||||
maximum-speed = "super-speed";
|
||||
};
|
||||
|
||||
&gem0 { /* mdio mio50/51 */
|
||||
status = "okay";
|
||||
phys = <&psgtr 0 PHY_TYPE_SGMII 0 0>;
|
||||
phy-handle = <&phy0>;
|
||||
phy-mode = "sgmii";
|
||||
is-internal-pcspma;
|
||||
};
|
||||
|
||||
&gem1 { /* mdio mio50/51, gem mio38 - mio49 */
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_gem1_default>;
|
||||
phy-handle = <&phy1>;
|
||||
phy-mode = "rgmii-id";
|
||||
|
||||
mdio: mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy0: ethernet-phy@4 { /* u81 */
|
||||
#phy-cells = <1>;
|
||||
compatible = "ethernet-phy-id2000.a231";
|
||||
reg = <4>;
|
||||
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
|
||||
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>;
|
||||
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
|
||||
ti,dp83867-rxctrl-strap-quirk;
|
||||
reset-assert-us = <100>;
|
||||
reset-deassert-us = <280>;
|
||||
reset-gpios = <&slg7xl45106 5 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
phy1: ethernet-phy@8 { /* u36 */
|
||||
#phy-cells = <1>;
|
||||
compatible = "ethernet-phy-id2000.a231";
|
||||
reg = <8>;
|
||||
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
|
||||
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>;
|
||||
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
|
||||
ti,dp83867-rxctrl-strap-quirk;
|
||||
reset-assert-us = <100>;
|
||||
reset-deassert-us = <280>;
|
||||
reset-gpios = <&slg7xl45106 6 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* gem2/gem3 via PL with phys u79@2 and u80@3 */
|
||||
|
||||
&pinctrl0 { /* required by spec */
|
||||
status = "okay";
|
||||
|
||||
pinctrl_uart1_default: uart1-default {
|
||||
conf {
|
||||
groups = "uart1_9_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
drive-strength = <12>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO37";
|
||||
bias-high-impedance;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO36";
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
mux {
|
||||
groups = "uart1_9_grp";
|
||||
function = "uart1";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_i2c1_default: i2c1-default {
|
||||
conf {
|
||||
groups = "i2c1_6_grp";
|
||||
bias-pull-up;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
mux {
|
||||
groups = "i2c1_6_grp";
|
||||
function = "i2c1";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_i2c1_gpio: i2c1-gpio {
|
||||
conf {
|
||||
groups = "gpio0_24_grp", "gpio0_25_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
mux {
|
||||
groups = "gpio0_24_grp", "gpio0_25_grp";
|
||||
function = "gpio0";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_gem1_default: gem1-default {
|
||||
conf {
|
||||
groups = "ethernet1_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO44", "MIO46", "MIO48";
|
||||
bias-high-impedance;
|
||||
low-power-disable;
|
||||
};
|
||||
|
||||
conf-bootstrap {
|
||||
pins = "MIO45", "MIO47", "MIO49";
|
||||
bias-disable;
|
||||
low-power-disable;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO38", "MIO39", "MIO40",
|
||||
"MIO41", "MIO42", "MIO43";
|
||||
bias-disable;
|
||||
low-power-enable;
|
||||
};
|
||||
|
||||
conf-mdio {
|
||||
groups = "mdio1_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
mux-mdio {
|
||||
function = "mdio1";
|
||||
groups = "mdio1_0_grp";
|
||||
};
|
||||
|
||||
mux {
|
||||
function = "ethernet1";
|
||||
groups = "ethernet1_0_grp";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_usb0_default: usb0-default {
|
||||
conf {
|
||||
groups = "usb0_0_grp";
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO52", "MIO53", "MIO55";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
|
||||
"MIO60", "MIO61", "MIO62", "MIO63";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
|
||||
mux {
|
||||
groups = "usb0_0_grp";
|
||||
function = "usb0";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_usb1_default: usb1-default {
|
||||
conf {
|
||||
groups = "usb1_0_grp";
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO64", "MIO65", "MIO67";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO66", "MIO68", "MIO69", "MIO70", "MIO71",
|
||||
"MIO72", "MIO73", "MIO74", "MIO75";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
|
||||
mux {
|
||||
groups = "usb1_0_grp";
|
||||
function = "usb1";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_uart1_default>;
|
||||
};
|
388
arch/arm/dts/zynqmp-sck-kr-g-revB.dts
Normal file
388
arch/arm/dts/zynqmp-sck-kr-g-revB.dts
Normal file
|
@ -0,0 +1,388 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* dts file for KR260 revB Carrier Card (A03 revision)
|
||||
*
|
||||
* (C) Copyright 2021 - 2022, Xilinx, Inc.
|
||||
*
|
||||
* Michal Simek <michal.simek@xilinx.com>
|
||||
*/
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/net/ti-dp83867.h>
|
||||
#include <dt-bindings/phy/phy.h>
|
||||
#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
&{/} {
|
||||
compatible = "xlnx,zynqmp-sk-kr260-revB",
|
||||
"xlnx,zynqmp-sk-kr260", "xlnx,zynqmp";
|
||||
|
||||
ina260-u14 {
|
||||
compatible = "iio-hwmon";
|
||||
io-channels = <&u14 0>, <&u14 1>, <&u14 2>;
|
||||
};
|
||||
|
||||
clk_125: clock0 { /* u87 - GEM0/1 */
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <125000000>;
|
||||
};
|
||||
|
||||
clk_27: clock1 { /* u86 - DP */
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <27000000>;
|
||||
};
|
||||
|
||||
clk_26: clock2 { /* u89 - USB */
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <26000000>;
|
||||
};
|
||||
|
||||
clk_156: clock3 { /* u90 - SFP+ */
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <156250000>;
|
||||
};
|
||||
|
||||
clk_25_0: clock4 { /* u92/u91 - GEM2 */
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <25000000>;
|
||||
};
|
||||
|
||||
clk_25_1: clock5 { /* u92/u91 - GEM3 */
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <25000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c1 { /* I2C_SCK C26/C27 - MIO from SOM */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pinctrl-names = "default", "gpio";
|
||||
pinctrl-0 = <&pinctrl_i2c1_default>;
|
||||
pinctrl-1 = <&pinctrl_i2c1_gpio>;
|
||||
scl-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
|
||||
sda-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
u14: ina260@40 { /* u14 */
|
||||
compatible = "ti,ina260";
|
||||
#io-channel-cells = <1>;
|
||||
label = "ina260-u14";
|
||||
reg = <0x40>;
|
||||
};
|
||||
|
||||
slg7xl45106: gpio@11 { /* u19 - reset logic */
|
||||
compatible = "dlg,slg7xl45106";
|
||||
reg = <0x11>;
|
||||
label = "resetchip";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-line-names = "USB0_PHY_RESET_B", "USB1_PHY_RESET_B",
|
||||
"SD_RESET_B", "USB0_HUB_RESET_B",
|
||||
"USB1_HUB_RESET_B", "PS_GEM0_RESET_B",
|
||||
"PS_GEM1_RESET_B", "";
|
||||
};
|
||||
|
||||
i2c-mux@74 { /* u18 */
|
||||
compatible = "nxp,pca9546";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x74>;
|
||||
usbhub_i2c0: i2c@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
};
|
||||
usbhub_i2c1: i2c@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
};
|
||||
/* Bus 2/3 are not connected */
|
||||
};
|
||||
|
||||
/* si5332@6a - u17 - clock-generator */
|
||||
};
|
||||
|
||||
/* GEM SGMII/DP and USB 3.0 */
|
||||
&psgtr {
|
||||
status = "okay";
|
||||
/* gem0/1, dp, usb */
|
||||
clocks = <&clk_125>, <&clk_27>, <&clk_26>;
|
||||
clock-names = "ref0", "ref1", "ref2";
|
||||
};
|
||||
|
||||
&zynqmp_dpsub {
|
||||
status = "okay";
|
||||
phy-names = "dp-phy0";
|
||||
phys = <&psgtr 1 PHY_TYPE_DP 0 1>;
|
||||
assigned-clock-rates = <27000000>, <25000000>, <300000000>;
|
||||
};
|
||||
|
||||
&zynqmp_dpdma {
|
||||
status = "okay";
|
||||
assigned-clock-rates = <600000000>;
|
||||
};
|
||||
|
||||
&usb0 { /* mio52 - mio63 */
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_usb0_default>;
|
||||
phy-names = "usb3-phy";
|
||||
phys = <&psgtr 2 PHY_TYPE_USB3 0 2>;
|
||||
reset-gpios = <&slg7xl45106 0 GPIO_ACTIVE_LOW>;
|
||||
assigned-clock-rates = <250000000>, <20000000>;
|
||||
|
||||
usbhub0: usb-hub { /* u43 */
|
||||
i2c-bus = <&usbhub_i2c0>;
|
||||
compatible = "microchip,usb5744";
|
||||
reset-gpios = <&slg7xl45106 3 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
usb2244: usb-sd { /* u38 */
|
||||
compatible = "microchip,usb2244";
|
||||
reset-gpios = <&slg7xl45106 2 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
&dwc3_0 {
|
||||
status = "okay";
|
||||
dr_mode = "host";
|
||||
snps,usb3_lpm_capable;
|
||||
maximum-speed = "super-speed";
|
||||
};
|
||||
|
||||
&usb1 { /* mio64 - mio75 */
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_usb1_default>;
|
||||
phy-names = "usb3-phy";
|
||||
phys = <&psgtr 3 PHY_TYPE_USB3 1 2>;
|
||||
reset-gpios = <&slg7xl45106 1 GPIO_ACTIVE_LOW>;
|
||||
assigned-clock-rates = <250000000>, <20000000>;
|
||||
|
||||
usbhub1: usb-hub { /* u84 */
|
||||
i2c-bus = <&usbhub_i2c1>;
|
||||
compatible = "microchip,usb5744";
|
||||
reset-gpios = <&slg7xl45106 4 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
&dwc3_1 {
|
||||
status = "okay";
|
||||
dr_mode = "host";
|
||||
snps,usb3_lpm_capable;
|
||||
maximum-speed = "super-speed";
|
||||
};
|
||||
|
||||
&gem0 { /* mdio mio50/51 */
|
||||
status = "okay";
|
||||
phys = <&psgtr 0 PHY_TYPE_SGMII 0 0>;
|
||||
phy-handle = <&phy0>;
|
||||
phy-mode = "sgmii";
|
||||
is-internal-pcspma;
|
||||
};
|
||||
|
||||
&gem1 { /* mdio mio50/51, gem mio38 - mio49 */
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_gem1_default>;
|
||||
phy-handle = <&phy1>;
|
||||
phy-mode = "rgmii-id";
|
||||
|
||||
mdio: mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy0: ethernet-phy@4 { /* u81 */
|
||||
#phy-cells = <1>;
|
||||
compatible = "ethernet-phy-id2000.a231";
|
||||
reg = <4>;
|
||||
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
|
||||
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>;
|
||||
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
|
||||
ti,dp83867-rxctrl-strap-quirk;
|
||||
reset-assert-us = <100>;
|
||||
reset-deassert-us = <280>;
|
||||
reset-gpios = <&slg7xl45106 5 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
phy1: ethernet-phy@8 { /* u36 */
|
||||
#phy-cells = <1>;
|
||||
compatible = "ethernet-phy-id2000.a231";
|
||||
reg = <8>;
|
||||
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
|
||||
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>;
|
||||
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
|
||||
ti,dp83867-rxctrl-strap-quirk;
|
||||
reset-assert-us = <100>;
|
||||
reset-deassert-us = <280>;
|
||||
reset-gpios = <&slg7xl45106 6 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* gem2/gem3 via PL with phys u79@2 and u80@3 */
|
||||
|
||||
&pinctrl0 { /* required by spec */
|
||||
status = "okay";
|
||||
|
||||
pinctrl_uart1_default: uart1-default {
|
||||
conf {
|
||||
groups = "uart1_9_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
drive-strength = <12>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO37";
|
||||
bias-high-impedance;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO36";
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
mux {
|
||||
groups = "uart1_9_grp";
|
||||
function = "uart1";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_i2c1_default: i2c1-default {
|
||||
conf {
|
||||
groups = "i2c1_6_grp";
|
||||
bias-pull-up;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
mux {
|
||||
groups = "i2c1_6_grp";
|
||||
function = "i2c1";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_i2c1_gpio: i2c1-gpio {
|
||||
conf {
|
||||
groups = "gpio0_24_grp", "gpio0_25_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
mux {
|
||||
groups = "gpio0_24_grp", "gpio0_25_grp";
|
||||
function = "gpio0";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_gem1_default: gem1-default {
|
||||
conf {
|
||||
groups = "ethernet1_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO44", "MIO46", "MIO48";
|
||||
bias-high-impedance;
|
||||
low-power-disable;
|
||||
};
|
||||
|
||||
conf-bootstrap {
|
||||
pins = "MIO45", "MIO47", "MIO49";
|
||||
bias-disable;
|
||||
low-power-disable;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO38", "MIO39", "MIO40",
|
||||
"MIO41", "MIO42", "MIO43";
|
||||
bias-disable;
|
||||
low-power-enable;
|
||||
};
|
||||
|
||||
conf-mdio {
|
||||
groups = "mdio1_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
mux-mdio {
|
||||
function = "mdio1";
|
||||
groups = "mdio1_0_grp";
|
||||
};
|
||||
|
||||
mux {
|
||||
function = "ethernet1";
|
||||
groups = "ethernet1_0_grp";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_usb0_default: usb0-default {
|
||||
conf {
|
||||
groups = "usb0_0_grp";
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO52", "MIO53", "MIO55";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
|
||||
"MIO60", "MIO61", "MIO62", "MIO63";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
|
||||
mux {
|
||||
groups = "usb0_0_grp";
|
||||
function = "usb0";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_usb1_default: usb1-default {
|
||||
conf {
|
||||
groups = "usb1_0_grp";
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO64", "MIO65", "MIO67";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO66", "MIO68", "MIO69", "MIO70", "MIO71",
|
||||
"MIO72", "MIO73", "MIO74", "MIO75";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
|
||||
mux {
|
||||
groups = "usb1_0_grp";
|
||||
function = "usb1";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_uart1_default>;
|
||||
};
|
|
@ -112,7 +112,7 @@
|
|||
};
|
||||
|
||||
&zynqmp_dpsub {
|
||||
status = "disabled";
|
||||
status = "okay";
|
||||
phy-names = "dp-phy0", "dp-phy1";
|
||||
phys = <&psgtr 1 PHY_TYPE_DP 0 0>, <&psgtr 0 PHY_TYPE_DP 1 0>;
|
||||
assigned-clock-rates = <27000000>, <25000000>, <300000000>;
|
||||
|
@ -285,19 +285,22 @@
|
|||
pinctrl_usb0_default: usb0-default {
|
||||
conf {
|
||||
groups = "usb0_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO52", "MIO53", "MIO55";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
|
||||
"MIO60", "MIO61", "MIO62", "MIO63";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
|
||||
mux {
|
||||
|
|
|
@ -272,19 +272,22 @@
|
|||
pinctrl_usb0_default: usb0-default {
|
||||
conf {
|
||||
groups = "usb0_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO52", "MIO53", "MIO55";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
|
||||
"MIO60", "MIO61", "MIO62", "MIO63";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
|
||||
mux {
|
||||
|
|
|
@ -187,19 +187,22 @@
|
|||
|
||||
conf {
|
||||
groups = "usb0_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO52", "MIO53", "MIO55";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
|
||||
"MIO60", "MIO61", "MIO62", "MIO63";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -335,19 +335,22 @@
|
|||
|
||||
conf {
|
||||
groups = "usb1_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO64", "MIO65", "MIO67";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO66", "MIO68", "MIO69", "MIO70", "MIO71",
|
||||
"MIO72", "MIO73", "MIO74", "MIO75";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -441,19 +441,22 @@
|
|||
|
||||
conf {
|
||||
groups = "usb0_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO52", "MIO53", "MIO55";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
|
||||
"MIO60", "MIO61", "MIO62", "MIO63";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -465,19 +468,22 @@
|
|||
|
||||
conf {
|
||||
groups = "usb1_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO64", "MIO65", "MIO67";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO66", "MIO68", "MIO69", "MIO70", "MIO71",
|
||||
"MIO72", "MIO73", "MIO74", "MIO75";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -795,19 +795,22 @@
|
|||
|
||||
conf {
|
||||
groups = "usb0_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO52", "MIO53", "MIO55";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
|
||||
"MIO60", "MIO61", "MIO62", "MIO63";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -402,20 +402,22 @@
|
|||
|
||||
conf {
|
||||
groups = "usb0_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
drive-strength = <12>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO52", "MIO53", "MIO55";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
|
||||
"MIO60", "MIO61", "MIO62", "MIO63";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -414,20 +414,22 @@
|
|||
|
||||
conf {
|
||||
groups = "usb0_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
drive-strength = <12>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO52", "MIO53", "MIO55";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
|
||||
"MIO60", "MIO61", "MIO62", "MIO63";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -793,19 +793,22 @@
|
|||
|
||||
conf {
|
||||
groups = "usb0_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO52", "MIO53", "MIO55";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
|
||||
"MIO60", "MIO61", "MIO62", "MIO63";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -652,19 +652,22 @@
|
|||
|
||||
conf {
|
||||
groups = "usb0_0_grp";
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
power-source = <IO_STANDARD_LVCMOS18>;
|
||||
};
|
||||
|
||||
conf-rx {
|
||||
pins = "MIO52", "MIO53", "MIO55";
|
||||
bias-high-impedance;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
|
||||
conf-tx {
|
||||
pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
|
||||
"MIO60", "MIO61", "MIO62", "MIO63";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -79,7 +79,10 @@ struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry,
|
|||
atfhandoffparams->magic[2] = 'N';
|
||||
atfhandoffparams->magic[3] = 'X';
|
||||
|
||||
debug("Creating handoff:\n");
|
||||
|
||||
if (bl32_entry) {
|
||||
debug(" to BL32 at 0x%x EL-1, Secure\n", (u32)bl32_entry);
|
||||
atfhandoffparams->partition[index].entry_point = bl32_entry;
|
||||
atfhandoffparams->partition[index].flags = FSBL_FLAGS_EL1 << FSBL_FLAGS_EL_SHIFT |
|
||||
FSBL_FLAGS_SECURE << FSBL_FLAGS_TZ_SHIFT;
|
||||
|
@ -87,6 +90,7 @@ struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry,
|
|||
}
|
||||
|
||||
if (bl33_entry) {
|
||||
debug(" to BL33 at 0x%x EL-2\n", (u32)bl33_entry);
|
||||
atfhandoffparams->partition[index].entry_point = bl33_entry;
|
||||
atfhandoffparams->partition[index].flags = FSBL_FLAGS_EL2 <<
|
||||
FSBL_FLAGS_EL_SHIFT;
|
||||
|
|
|
@ -4,6 +4,9 @@ menu "M68000 architecture"
|
|||
config SYS_ARCH
|
||||
default "m68k"
|
||||
|
||||
config NEEDS_MANUAL_RELOC
|
||||
def_bool y
|
||||
|
||||
# processor family
|
||||
config MCF520x
|
||||
select OF_CONTROL
|
||||
|
|
|
@ -4,6 +4,20 @@ menu "MicroBlaze architecture"
|
|||
config SYS_ARCH
|
||||
default "microblaze"
|
||||
|
||||
config NEEDS_MANUAL_RELOC
|
||||
bool "Disable position-independent pre-relocation code"
|
||||
default y
|
||||
help
|
||||
U-Boot expects to be linked to a specific hard-coded address, and to
|
||||
be loaded to and run from that address. This option lifts that
|
||||
restriction, thus allowing the code to be loaded to and executed from
|
||||
almost any 4K aligned address. This logic relies on the relocation
|
||||
information that is embedded in the binary to support U-Boot
|
||||
relocating itself to the top-of-RAM later during execution.
|
||||
|
||||
config STATIC_RELA
|
||||
def_bool y if !NEEDS_MANUAL_RELOC
|
||||
|
||||
choice
|
||||
prompt "Target select"
|
||||
optional
|
||||
|
@ -25,14 +39,6 @@ config TARGET_MICROBLAZE_GENERIC
|
|||
|
||||
endchoice
|
||||
|
||||
config DCACHE
|
||||
bool "Enable dcache support"
|
||||
default y
|
||||
|
||||
config ICACHE
|
||||
bool "Enable icache support"
|
||||
default y
|
||||
|
||||
source "board/xilinx/Kconfig"
|
||||
source "board/xilinx/microblaze-generic/Kconfig"
|
||||
|
||||
|
|
|
@ -16,3 +16,14 @@ LDFLAGS_FINAL += --gc-sections
|
|||
ifeq ($(CONFIG_SPL_BUILD),)
|
||||
PLATFORM_CPPFLAGS += -fPIC
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_STATIC_RELA),y)
|
||||
PLATFORM_CPPFLAGS += -fPIC
|
||||
LDFLAGS_u-boot += -pic
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SYS_LITTLE_ENDIAN),y)
|
||||
PLATFORM_ELFFLAGS += -B microblaze $(OBJCOPYFLAGS) -O elf32-microblazeel
|
||||
else
|
||||
PLATFORM_ELFFLAGS += -B microblaze $(OBJCOPYFLAGS) -O elf32-microblaze
|
||||
endif
|
||||
|
|
|
@ -5,5 +5,7 @@
|
|||
|
||||
extra-y = start.o
|
||||
obj-y = irq.o
|
||||
obj-y += interrupts.o cache.o exception.o timer.o
|
||||
obj-y += interrupts.o cache.o exception.o cpuinfo.o
|
||||
obj-$(CONFIG_STATIC_RELA) += relocate.o
|
||||
obj-$(CONFIG_XILINX_MICROBLAZE0_PVR) += pvr.o
|
||||
obj-$(CONFIG_SPL_BUILD) += spl.o
|
||||
|
|
|
@ -9,6 +9,61 @@
|
|||
#include <cpu_func.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/cpuinfo.h>
|
||||
#include <asm/global_data.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static void __invalidate_icache(ulong addr, ulong size)
|
||||
{
|
||||
if (CONFIG_IS_ENABLED(XILINX_MICROBLAZE0_USE_WIC)) {
|
||||
for (int i = 0; i < size;
|
||||
i += gd_cpuinfo()->icache_line_length) {
|
||||
asm volatile (
|
||||
"wic %0, r0;"
|
||||
"nop;"
|
||||
:
|
||||
: "r" (addr + i)
|
||||
: "memory");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void invalidate_icache_all(void)
|
||||
{
|
||||
__invalidate_icache(0, gd_cpuinfo()->icache_size);
|
||||
}
|
||||
|
||||
static void __flush_dcache(ulong addr, ulong size)
|
||||
{
|
||||
if (CONFIG_IS_ENABLED(XILINX_MICROBLAZE0_USE_WDC)) {
|
||||
for (int i = 0; i < size;
|
||||
i += gd_cpuinfo()->dcache_line_length) {
|
||||
asm volatile (
|
||||
"wdc.flush %0, r0;"
|
||||
"nop;"
|
||||
:
|
||||
: "r" (addr + i)
|
||||
: "memory");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flush_dcache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
if (start >= end) {
|
||||
debug("Invalid dcache range - start: 0x%08lx end: 0x%08lx\n",
|
||||
start, end);
|
||||
return;
|
||||
}
|
||||
|
||||
__flush_dcache(start, end - start);
|
||||
}
|
||||
|
||||
void flush_dcache_all(void)
|
||||
{
|
||||
__flush_dcache(0, gd_cpuinfo()->dcache_size);
|
||||
}
|
||||
|
||||
int dcache_status(void)
|
||||
{
|
||||
|
@ -37,8 +92,8 @@ void icache_enable(void)
|
|||
|
||||
void icache_disable(void)
|
||||
{
|
||||
/* we are not generate ICACHE size -> flush whole cache */
|
||||
flush_cache(0, 32768);
|
||||
invalidate_icache_all();
|
||||
|
||||
MSRCLR(0x20);
|
||||
}
|
||||
|
||||
|
@ -49,26 +104,19 @@ void dcache_enable(void)
|
|||
|
||||
void dcache_disable(void)
|
||||
{
|
||||
#ifdef XILINX_USE_DCACHE
|
||||
flush_cache(0, XILINX_DCACHE_BYTE_SIZE);
|
||||
#endif
|
||||
flush_dcache_all();
|
||||
|
||||
MSRCLR(0x80);
|
||||
}
|
||||
|
||||
void flush_cache(ulong addr, ulong size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i += 4)
|
||||
asm volatile (
|
||||
#ifdef CONFIG_ICACHE
|
||||
"wic %0, r0;"
|
||||
#endif
|
||||
"nop;"
|
||||
#ifdef CONFIG_DCACHE
|
||||
"wdc.flush %0, r0;"
|
||||
#endif
|
||||
"nop;"
|
||||
:
|
||||
: "r" (addr + i)
|
||||
: "memory");
|
||||
__invalidate_icache(addr, size);
|
||||
__flush_dcache(addr, size);
|
||||
}
|
||||
|
||||
void flush_cache_all(void)
|
||||
{
|
||||
invalidate_icache_all();
|
||||
flush_dcache_all();
|
||||
}
|
||||
|
|
131
arch/microblaze/cpu/cpuinfo.c
Normal file
131
arch/microblaze/cpu/cpuinfo.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2022, Ovidiu Panait <ovpanait@gmail.com>
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <asm/cpuinfo.h>
|
||||
#include <asm/global_data.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if CONFIG_IS_ENABLED(CPU_MICROBLAZE)
|
||||
/* These key value are as per MBV field in PVR0 */
|
||||
static const struct microblaze_version_map cpu_ver_lookup[] = {
|
||||
{"5.00.a", 0x01},
|
||||
{"5.00.b", 0x02},
|
||||
{"5.00.c", 0x03},
|
||||
{"6.00.a", 0x04},
|
||||
{"6.00.b", 0x06},
|
||||
{"7.00.a", 0x05},
|
||||
{"7.00.b", 0x07},
|
||||
{"7.10.a", 0x08},
|
||||
{"7.10.b", 0x09},
|
||||
{"7.10.c", 0x0a},
|
||||
{"7.10.d", 0x0b},
|
||||
{"7.20.a", 0x0c},
|
||||
{"7.20.b", 0x0d},
|
||||
{"7.20.c", 0x0e},
|
||||
{"7.20.d", 0x0f},
|
||||
{"7.30.a", 0x10},
|
||||
{"7.30.b", 0x11},
|
||||
{"8.00.a", 0x12},
|
||||
{"8.00.b", 0x13},
|
||||
{"8.10.a", 0x14},
|
||||
{"8.20.a", 0x15},
|
||||
{"8.20.b", 0x16},
|
||||
{"8.30.a", 0x17},
|
||||
{"8.40.a", 0x18},
|
||||
{"8.40.b", 0x19},
|
||||
{"8.50.a", 0x1a},
|
||||
{"8.50.b", 0x1c},
|
||||
{"8.50.c", 0x1e},
|
||||
{"9.0", 0x1b},
|
||||
{"9.1", 0x1d},
|
||||
{"9.2", 0x1f},
|
||||
{"9.3", 0x20},
|
||||
{"9.4", 0x21},
|
||||
{"9.5", 0x22},
|
||||
{"9.6", 0x23},
|
||||
{"10.0", 0x24},
|
||||
{"11.0", 0x25},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
static const struct microblaze_version_map family_string_lookup[] = {
|
||||
{"virtex2", 0x4},
|
||||
{"virtex2pro", 0x5},
|
||||
{"spartan3", 0x6},
|
||||
{"virtex4", 0x7},
|
||||
{"virtex5", 0x8},
|
||||
{"spartan3e", 0x9},
|
||||
{"spartan3a", 0xa},
|
||||
{"spartan3an", 0xb},
|
||||
{"spartan3adsp", 0xc},
|
||||
{"spartan6", 0xd},
|
||||
{"virtex6", 0xe},
|
||||
{"virtex7", 0xf},
|
||||
/* FIXME There is no key code defined for spartan2 */
|
||||
{"spartan2", 0xf0},
|
||||
{"kintex7", 0x10},
|
||||
{"artix7", 0x11},
|
||||
{"zynq7000", 0x12},
|
||||
{"UltraScale Virtex", 0x13},
|
||||
{"UltraScale Kintex", 0x14},
|
||||
{"UltraScale+ Zynq", 0x15},
|
||||
{"UltraScale+ Virtex", 0x16},
|
||||
{"UltraScale+ Kintex", 0x17},
|
||||
{"Spartan7", 0x18},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
static const char *lookup_string(u32 code,
|
||||
const struct microblaze_version_map *entry)
|
||||
{
|
||||
for (; entry->string; ++entry)
|
||||
if (entry->code == code)
|
||||
return entry->string;
|
||||
|
||||
return "(unknown)";
|
||||
}
|
||||
|
||||
static const u32 lookup_code(const char *string,
|
||||
const struct microblaze_version_map *entry)
|
||||
{
|
||||
for (; entry->string; ++entry)
|
||||
if (!strcmp(entry->string, string))
|
||||
return entry->code;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *microblaze_lookup_fpga_family_string(const u32 code)
|
||||
{
|
||||
return lookup_string(code, family_string_lookup);
|
||||
}
|
||||
|
||||
const char *microblaze_lookup_cpu_version_string(const u32 code)
|
||||
{
|
||||
return lookup_string(code, cpu_ver_lookup);
|
||||
}
|
||||
|
||||
const u32 microblaze_lookup_fpga_family_code(const char *string)
|
||||
{
|
||||
return lookup_code(string, family_string_lookup);
|
||||
}
|
||||
|
||||
const u32 microblaze_lookup_cpu_version_code(const char *string)
|
||||
{
|
||||
return lookup_code(string, cpu_ver_lookup);
|
||||
}
|
||||
#endif /* CONFIG_CPU_MICROBLAZE */
|
||||
|
||||
void microblaze_early_cpuinfo_init(void)
|
||||
{
|
||||
struct microblaze_cpuinfo *ci = gd_cpuinfo();
|
||||
|
||||
ci->icache_size = CONFIG_XILINX_MICROBLAZE0_ICACHE_SIZE;
|
||||
ci->icache_line_length = 4;
|
||||
|
||||
ci->dcache_size = CONFIG_XILINX_MICROBLAZE0_DCACHE_SIZE;
|
||||
ci->dcache_line_length = 4;
|
||||
}
|
|
@ -16,7 +16,7 @@ void _hw_exception_handler (void)
|
|||
|
||||
/* loading address of exception EAR */
|
||||
MFS(address, rear);
|
||||
/* loading excetpion state register ESR */
|
||||
/* loading exception state register ESR */
|
||||
MFS(state, resr);
|
||||
printf("Hardware exception at 0x%x address\n", address);
|
||||
R17(address);
|
||||
|
|
|
@ -8,17 +8,8 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <fdtdec.h>
|
||||
#include <irq_func.h>
|
||||
#include <log.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/microblaze_intc.h>
|
||||
#include <asm/asm.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void enable_interrupts(void)
|
||||
{
|
||||
debug("Enable interrupts for the whole CPU\n");
|
||||
|
@ -34,183 +25,12 @@ int disable_interrupts(void)
|
|||
return (msr & 0x2) != 0;
|
||||
}
|
||||
|
||||
static struct irq_action *vecs;
|
||||
static u32 irq_no;
|
||||
|
||||
/* mapping structure to interrupt controller */
|
||||
microblaze_intc_t *intc;
|
||||
|
||||
/* default handler */
|
||||
static void def_hdlr(void)
|
||||
{
|
||||
puts("def_hdlr\n");
|
||||
}
|
||||
|
||||
static void enable_one_interrupt(int irq)
|
||||
{
|
||||
int mask;
|
||||
int offset = 1;
|
||||
|
||||
offset <<= irq;
|
||||
mask = intc->ier;
|
||||
intc->ier = (mask | offset);
|
||||
|
||||
debug("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
|
||||
intc->ier);
|
||||
debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
|
||||
intc->iar, intc->mer);
|
||||
}
|
||||
|
||||
static void disable_one_interrupt(int irq)
|
||||
{
|
||||
int mask;
|
||||
int offset = 1;
|
||||
|
||||
offset <<= irq;
|
||||
mask = intc->ier;
|
||||
intc->ier = (mask & ~offset);
|
||||
|
||||
debug("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
|
||||
intc->ier);
|
||||
debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
|
||||
intc->iar, intc->mer);
|
||||
}
|
||||
|
||||
int install_interrupt_handler(int irq, interrupt_handler_t *hdlr, void *arg)
|
||||
{
|
||||
struct irq_action *act;
|
||||
|
||||
/* irq out of range */
|
||||
if ((irq < 0) || (irq > irq_no)) {
|
||||
puts("IRQ out of range\n");
|
||||
return -1;
|
||||
}
|
||||
act = &vecs[irq];
|
||||
if (hdlr) { /* enable */
|
||||
act->handler = hdlr;
|
||||
act->arg = arg;
|
||||
act->count = 0;
|
||||
enable_one_interrupt(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Disable */
|
||||
act->handler = (interrupt_handler_t *)def_hdlr;
|
||||
act->arg = (void *)irq;
|
||||
disable_one_interrupt(irq);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* initialization interrupt controller - hardware */
|
||||
static void intc_init(void)
|
||||
{
|
||||
intc->mer = 0;
|
||||
intc->ier = 0;
|
||||
intc->iar = 0xFFFFFFFF;
|
||||
/* XIntc_Start - hw_interrupt enable and all interrupt enable */
|
||||
intc->mer = 0x3;
|
||||
|
||||
debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
|
||||
intc->iar, intc->mer);
|
||||
}
|
||||
|
||||
int interrupt_init(void)
|
||||
{
|
||||
int i;
|
||||
const void *blob = gd->fdt_blob;
|
||||
int node = 0;
|
||||
|
||||
debug("INTC: Initialization\n");
|
||||
|
||||
node = fdt_node_offset_by_compatible(blob, node,
|
||||
"xlnx,xps-intc-1.00.a");
|
||||
if (node != -1) {
|
||||
fdt_addr_t base = fdtdec_get_addr(blob, node, "reg");
|
||||
if (base == FDT_ADDR_T_NONE)
|
||||
return -1;
|
||||
|
||||
debug("INTC: Base addr %lx\n", base);
|
||||
intc = (microblaze_intc_t *)base;
|
||||
irq_no = fdtdec_get_int(blob, node, "xlnx,num-intr-inputs", 0);
|
||||
debug("INTC: IRQ NO %x\n", irq_no);
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (irq_no) {
|
||||
vecs = calloc(1, sizeof(struct irq_action) * irq_no);
|
||||
if (vecs == NULL) {
|
||||
puts("Interrupt vector allocation failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* initialize irq list */
|
||||
for (i = 0; i < irq_no; i++) {
|
||||
vecs[i].handler = (interrupt_handler_t *)def_hdlr;
|
||||
vecs[i].arg = (void *)i;
|
||||
vecs[i].count = 0;
|
||||
}
|
||||
/* initialize intc controller */
|
||||
intc_init();
|
||||
enable_interrupts();
|
||||
} else {
|
||||
puts("Undefined interrupt controller\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void interrupt_handler(void)
|
||||
{
|
||||
int irqs = intc->ivr; /* find active interrupt */
|
||||
int mask = 1;
|
||||
int value;
|
||||
struct irq_action *act = vecs + irqs;
|
||||
|
||||
debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
|
||||
intc->iar, intc->mer);
|
||||
#ifdef DEBUG
|
||||
R14(value);
|
||||
#endif
|
||||
debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
|
||||
|
||||
debug("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n",
|
||||
(u32)act->handler, act->count, (u32)act->arg);
|
||||
act->handler(act->arg);
|
||||
act->count++;
|
||||
|
||||
intc->iar = mask << irqs;
|
||||
|
||||
debug("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
|
||||
intc->ier, intc->iar, intc->mer);
|
||||
#ifdef DEBUG
|
||||
R14(value);
|
||||
#endif
|
||||
debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
|
||||
panic("Interrupt occurred\n");
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CMD_IRQ)
|
||||
int do_irqinfo(struct cmd_tbl *cmdtp, int flag, int argc, const char *argv[])
|
||||
{
|
||||
int i;
|
||||
struct irq_action *act = vecs;
|
||||
|
||||
if (irq_no) {
|
||||
puts("\nInterrupt-Information:\n\n"
|
||||
"Nr Routine Arg Count\n"
|
||||
"-----------------------------\n");
|
||||
|
||||
for (i = 0; i < irq_no; i++) {
|
||||
if (act->handler != (interrupt_handler_t *)def_hdlr) {
|
||||
printf("%02d %08x %08x %d\n", i,
|
||||
(int)act->handler, (int)act->arg,
|
||||
act->count);
|
||||
}
|
||||
act++;
|
||||
}
|
||||
puts("\n");
|
||||
} else {
|
||||
puts("Undefined interrupt controller\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
41
arch/microblaze/cpu/pvr.c
Normal file
41
arch/microblaze/cpu/pvr.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2022, Ovidiu Panait <ovpanait@gmail.com>
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/pvr.h>
|
||||
|
||||
int microblaze_cpu_has_pvr_full(void)
|
||||
{
|
||||
u32 msr, pvr0;
|
||||
|
||||
MFS(msr, rmsr);
|
||||
if (!(msr & PVR_MSR_BIT))
|
||||
return 0;
|
||||
|
||||
get_pvr(0, pvr0);
|
||||
debug("%s: pvr0 is 0x%08x\n", __func__, pvr0);
|
||||
|
||||
if (!(pvr0 & PVR0_PVR_FULL_MASK))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void microblaze_get_all_pvrs(u32 pvr[PVR_FULL_COUNT])
|
||||
{
|
||||
get_pvr(0, pvr[0]);
|
||||
get_pvr(1, pvr[1]);
|
||||
get_pvr(2, pvr[2]);
|
||||
get_pvr(3, pvr[3]);
|
||||
get_pvr(4, pvr[4]);
|
||||
get_pvr(5, pvr[5]);
|
||||
get_pvr(6, pvr[6]);
|
||||
get_pvr(7, pvr[7]);
|
||||
get_pvr(8, pvr[8]);
|
||||
get_pvr(9, pvr[9]);
|
||||
get_pvr(10, pvr[10]);
|
||||
get_pvr(11, pvr[11]);
|
||||
get_pvr(12, pvr[12]);
|
||||
}
|
111
arch/microblaze/cpu/relocate.c
Normal file
111
arch/microblaze/cpu/relocate.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* (C) Copyright 2022 Advanced Micro Devices, Inc
|
||||
* Michal Simek <michal.simek@amd.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <elf.h>
|
||||
|
||||
#define R_MICROBLAZE_NONE 0
|
||||
#define R_MICROBLAZE_32 1
|
||||
#define R_MICROBLAZE_REL 16
|
||||
#define R_MICROBLAZE_GLOB_DAT 18
|
||||
|
||||
/**
|
||||
* mb_fix_rela - update relocation to new address
|
||||
* @reloc_addr: new relocation address
|
||||
* @verbose: enable version messages
|
||||
* @rela_start: rela section start
|
||||
* @rela_end: rela section end
|
||||
* @dyn_start: dynamic section start
|
||||
* @origin_addr: address where u-boot starts(doesn't need to be CONFIG_SYS_TEXT_BASE)
|
||||
*/
|
||||
void mb_fix_rela(u32 reloc_addr, u32 verbose, u32 rela_start,
|
||||
u32 rela_end, u32 dyn_start, u32 origin_addr)
|
||||
{
|
||||
u32 num, type, mask, i, reloc_off;
|
||||
|
||||
/*
|
||||
* Return in case u-boot.elf is used directly.
|
||||
* Skip it when u-boot.bin is loaded to different address than
|
||||
* CONFIG_SYS_TEXT_BASE. In this case relocation is necessary to run.
|
||||
*/
|
||||
if (reloc_addr == CONFIG_SYS_TEXT_BASE) {
|
||||
debug_cond(verbose,
|
||||
"Relocation address is the same - skip relocation\n");
|
||||
return;
|
||||
}
|
||||
|
||||
reloc_off = reloc_addr - origin_addr;
|
||||
|
||||
debug_cond(verbose, "Relocation address:\t0x%08x\n", reloc_addr);
|
||||
debug_cond(verbose, "Relocation offset:\t0x%08x\n", reloc_off);
|
||||
debug_cond(verbose, "Origin address:\t0x%08x\n", origin_addr);
|
||||
debug_cond(verbose, "Rela start:\t0x%08x\n", rela_start);
|
||||
debug_cond(verbose, "Rela end:\t0x%08x\n", rela_end);
|
||||
debug_cond(verbose, "Dynsym start:\t0x%08x\n", dyn_start);
|
||||
|
||||
num = (rela_end - rela_start) / sizeof(Elf32_Rela);
|
||||
|
||||
debug_cond(verbose, "Number of entries:\t%u\n", num);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
Elf32_Rela *rela;
|
||||
u32 temp;
|
||||
|
||||
rela = (Elf32_Rela *)(rela_start + sizeof(Elf32_Rela) * i);
|
||||
|
||||
mask = 0xffULL; /* would be different on 32-bit */
|
||||
type = rela->r_info & mask;
|
||||
|
||||
debug_cond(verbose, "\nRela possition:\t%d/0x%x\n",
|
||||
i, (u32)rela);
|
||||
|
||||
switch (type) {
|
||||
case R_MICROBLAZE_REL:
|
||||
temp = *(u32 *)rela->r_offset;
|
||||
|
||||
debug_cond(verbose, "Type:\tREL\n");
|
||||
debug_cond(verbose, "Rela r_offset:\t\t0x%x\n", rela->r_offset);
|
||||
debug_cond(verbose, "Rela r_info:\t\t0x%x\n", rela->r_info);
|
||||
debug_cond(verbose, "Rela r_addend:\t\t0x%x\n", rela->r_addend);
|
||||
debug_cond(verbose, "Value at r_offset:\t0x%x\n", temp);
|
||||
|
||||
rela->r_offset += reloc_off;
|
||||
rela->r_addend += reloc_off;
|
||||
|
||||
temp = *(u32 *)rela->r_offset;
|
||||
temp += reloc_off;
|
||||
*(u32 *)rela->r_offset = temp;
|
||||
|
||||
debug_cond(verbose, "New:Rela r_offset:\t0x%x\n", rela->r_offset);
|
||||
debug_cond(verbose, "New:Rela r_addend:\t0x%x\n", rela->r_addend);
|
||||
debug_cond(verbose, "New:Value at r_offset:\t0x%x\n", temp);
|
||||
break;
|
||||
case R_MICROBLAZE_32:
|
||||
case R_MICROBLAZE_GLOB_DAT:
|
||||
debug_cond(verbose, "Type:\t(32/GLOB) %u\n", type);
|
||||
debug_cond(verbose, "Rela r_offset:\t\t0x%x\n", rela->r_offset);
|
||||
debug_cond(verbose, "Rela r_info:\t\t0x%x\n", rela->r_info);
|
||||
debug_cond(verbose, "Rela r_addend:\t\t0x%x\n", rela->r_addend);
|
||||
debug_cond(verbose, "Value at r_offset:\t0x%x\n", temp);
|
||||
|
||||
rela->r_offset += reloc_off;
|
||||
|
||||
temp = *(u32 *)rela->r_offset;
|
||||
temp += reloc_off;
|
||||
*(u32 *)rela->r_offset = temp;
|
||||
|
||||
debug_cond(verbose, "New:Rela r_offset:\t0x%x\n", rela->r_offset);
|
||||
debug_cond(verbose, "New:Value at r_offset:\t0x%x\n", temp);
|
||||
break;
|
||||
case R_MICROBLAZE_NONE:
|
||||
debug_cond(verbose, "R_MICROBLAZE_NONE - skip\n");
|
||||
break;
|
||||
default:
|
||||
debug_cond(verbose, "warning: unsupported relocation type %d at %x\n",
|
||||
type, rela->r_offset);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,18 +10,64 @@
|
|||
#include <asm-offsets.h>
|
||||
#include <config.h>
|
||||
|
||||
#if defined(CONFIG_STATIC_RELA)
|
||||
#define SYM_ADDR(reg, reg_add, symbol) \
|
||||
mfs r20, rpc; \
|
||||
addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8; \
|
||||
lwi reg, r20, symbol@GOT; \
|
||||
addk reg, reg reg_add;
|
||||
#else
|
||||
#define SYM_ADDR(reg, reg_add, symbol) \
|
||||
addi reg, reg_add, symbol
|
||||
#endif
|
||||
|
||||
.text
|
||||
.global _start
|
||||
_start:
|
||||
mts rmsr, r0 /* disable cache */
|
||||
mfs r20, rpc
|
||||
addi r20, r20, -4
|
||||
|
||||
addi r8, r0, _end
|
||||
mts rslr, r8
|
||||
mts rslr, r0
|
||||
mts rshr, r20
|
||||
|
||||
#if defined(CONFIG_SPL_BUILD)
|
||||
addi r1, r0, CONFIG_SPL_STACK
|
||||
#else
|
||||
addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET
|
||||
add r1, r0, r20
|
||||
#if defined(CONFIG_STATIC_RELA)
|
||||
bri 1f
|
||||
|
||||
/* Force alignment for easier ASM code below */
|
||||
#define ALIGNMENT_ADDR 0x20
|
||||
.align 4
|
||||
uboot_dyn_start:
|
||||
.word __rel_dyn_start
|
||||
|
||||
uboot_dyn_end:
|
||||
.word __rel_dyn_end
|
||||
|
||||
uboot_sym_start:
|
||||
.word __dyn_sym_start
|
||||
1:
|
||||
|
||||
addi r5, r20, 0
|
||||
add r6, r0, r0
|
||||
|
||||
lwi r7, r20, ALIGNMENT_ADDR
|
||||
addi r7, r7, -CONFIG_SYS_TEXT_BASE
|
||||
add r7, r7, r5
|
||||
lwi r8, r20, ALIGNMENT_ADDR + 0x4
|
||||
addi r8, r8, -CONFIG_SYS_TEXT_BASE
|
||||
add r8, r8, r5
|
||||
lwi r9, r20, ALIGNMENT_ADDR + 0x8
|
||||
addi r9, r9, -CONFIG_SYS_TEXT_BASE
|
||||
add r9, r9, r5
|
||||
addi r10, r0, CONFIG_SYS_TEXT_BASE
|
||||
|
||||
brlid r15, mb_fix_rela
|
||||
nop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
addi r1, r1, -4 /* Decrement SP to top of memory */
|
||||
|
@ -29,7 +75,7 @@ _start:
|
|||
/* Call board_init_f_alloc_reserve with the current stack pointer as
|
||||
* parameter. */
|
||||
add r5, r0, r1
|
||||
bralid r15, board_init_f_alloc_reserve
|
||||
brlid r15, board_init_f_alloc_reserve
|
||||
nop
|
||||
|
||||
/* board_init_f_alloc_reserve returns a pointer to the allocated area
|
||||
|
@ -41,20 +87,25 @@ _start:
|
|||
/* Call board_init_f_init_reserve with the address returned by
|
||||
* board_init_f_alloc_reserve as parameter. */
|
||||
add r5, r0, r3
|
||||
bralid r15, board_init_f_init_reserve
|
||||
brlid r15, board_init_f_init_reserve
|
||||
nop
|
||||
|
||||
#if !defined(CONFIG_SPL_BUILD)
|
||||
/* Setup vectors with pre-relocation symbols */
|
||||
or r5, r0, r0
|
||||
bralid r15, __setup_exceptions
|
||||
brlid r15, __setup_exceptions
|
||||
nop
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize global data cpuinfo with default values (cache
|
||||
* size, cache line size, etc).
|
||||
*/
|
||||
brlid r15, microblaze_early_cpuinfo_init
|
||||
nop
|
||||
|
||||
/* Flush cache before enable cache */
|
||||
addik r5, r0, 0
|
||||
addik r6, r0, XILINX_DCACHE_BYTE_SIZE
|
||||
bralid r15, flush_cache
|
||||
brlid r15, flush_cache_all
|
||||
nop
|
||||
|
||||
/* enable instruction and data cache */
|
||||
|
@ -64,8 +115,8 @@ _start:
|
|||
|
||||
clear_bss:
|
||||
/* clear BSS segments */
|
||||
addi r5, r0, __bss_start
|
||||
addi r4, r0, __bss_end
|
||||
SYM_ADDR(r5, r0, __bss_start)
|
||||
SYM_ADDR(r4, r0, __bss_end)
|
||||
cmp r6, r5, r4
|
||||
beqi r6, 3f
|
||||
2:
|
||||
|
@ -75,14 +126,14 @@ clear_bss:
|
|||
bnei r6, 2b
|
||||
3: /* jumping to board_init */
|
||||
#ifdef CONFIG_DEBUG_UART
|
||||
bralid r15, debug_uart_init
|
||||
brlid r15, debug_uart_init
|
||||
nop
|
||||
#endif
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
or r5, r0, r0 /* flags - empty */
|
||||
brai board_init_f
|
||||
bri board_init_f
|
||||
#else
|
||||
brai board_init_r
|
||||
bri board_init_r
|
||||
#endif
|
||||
1: bri 1b
|
||||
|
||||
|
@ -141,7 +192,8 @@ __setup_exceptions:
|
|||
swi r2, r4, 0x0 /* reset address - imm opcode */
|
||||
swi r3, r4, 0x4 /* reset address - brai opcode */
|
||||
|
||||
addik r6, r0, CONFIG_SYS_TEXT_BASE
|
||||
SYM_ADDR(r6, r0, _start)
|
||||
/* Intentionally keep reset vector back to origin u-boot location */
|
||||
sw r6, r1, r0
|
||||
lhu r7, r1, r10
|
||||
rsubi r8, r10, 0x2
|
||||
|
@ -154,7 +206,7 @@ __setup_exceptions:
|
|||
swi r2, r4, 0x8 /* user vector exception - imm opcode */
|
||||
swi r3, r4, 0xC /* user vector exception - brai opcode */
|
||||
|
||||
addik r6, r5, _exception_handler
|
||||
SYM_ADDR(r6, r5, _exception_handler)
|
||||
sw r6, r1, r0
|
||||
/*
|
||||
* BIG ENDIAN memory map for user exception
|
||||
|
@ -187,7 +239,7 @@ __setup_exceptions:
|
|||
swi r2, r4, 0x10 /* interrupt - imm opcode */
|
||||
swi r3, r4, 0x14 /* interrupt - brai opcode */
|
||||
|
||||
addik r6, r5, _interrupt_handler
|
||||
SYM_ADDR(r6, r5, _interrupt_handler)
|
||||
sw r6, r1, r0
|
||||
lhu r7, r1, r10
|
||||
rsubi r8, r10, 0x12
|
||||
|
@ -199,7 +251,7 @@ __setup_exceptions:
|
|||
swi r2, r4, 0x20 /* hardware exception - imm opcode */
|
||||
swi r3, r4, 0x24 /* hardware exception - brai opcode */
|
||||
|
||||
addik r6, r5, _hw_exception_handler
|
||||
SYM_ADDR(r6, r5, _hw_exception_handler)
|
||||
sw r6, r1, r0
|
||||
lhu r7, r1, r10
|
||||
rsubi r8, r10, 0x22
|
||||
|
@ -220,39 +272,6 @@ __setup_exceptions:
|
|||
or r0, r0, r0
|
||||
.end __setup_exceptions
|
||||
|
||||
/*
|
||||
* Read 16bit little endian
|
||||
*/
|
||||
.text
|
||||
.global in16
|
||||
.ent in16
|
||||
.align 2
|
||||
in16: lhu r3, r0, r5
|
||||
bslli r4, r3, 8
|
||||
bsrli r3, r3, 8
|
||||
andi r4, r4, 0xffff
|
||||
or r3, r3, r4
|
||||
rtsd r15, 8
|
||||
sext16 r3, r3
|
||||
.end in16
|
||||
|
||||
/*
|
||||
* Write 16bit little endian
|
||||
* first parameter(r5) - address, second(r6) - short value
|
||||
*/
|
||||
.text
|
||||
.global out16
|
||||
.ent out16
|
||||
.align 2
|
||||
out16: bslli r3, r6, 8
|
||||
bsrli r6, r6, 8
|
||||
andi r3, r3, 0xffff
|
||||
or r3, r3, r6
|
||||
sh r3, r0, r5
|
||||
rtsd r15, 8
|
||||
or r0, r0, r0
|
||||
.end out16
|
||||
|
||||
/*
|
||||
* Relocate u-boot
|
||||
*/
|
||||
|
@ -267,31 +286,54 @@ relocate_code:
|
|||
* r7 - reloc_addr
|
||||
*/
|
||||
addi r1, r5, 0 /* Start to use new SP */
|
||||
mts rshr, r1
|
||||
addi r31, r6, 0 /* Start to use new GD */
|
||||
|
||||
add r23, r0, r7 /* Move reloc addr to r23 */
|
||||
/* Relocate text and data - r12 temp value */
|
||||
addi r21, r0, _start
|
||||
addi r22, r0, _end - 4 /* Include BSS too */
|
||||
SYM_ADDR(r21, r0, _start)
|
||||
SYM_ADDR(r22, r0, _end) /* Include BSS too */
|
||||
addi r22, r22, -4
|
||||
|
||||
rsub r6, r21, r22
|
||||
or r5, r0, r0
|
||||
1: lw r12, r21, r5 /* Load u-boot data */
|
||||
sw r12, r23, r5 /* Write zero to loc */
|
||||
sw r12, r7, r5 /* Write zero to loc */
|
||||
cmp r12, r5, r6 /* Check if we have reach the end */
|
||||
bneid r12, 1b
|
||||
addi r5, r5, 4 /* Increment to next loc - relocate code */
|
||||
|
||||
/* R23 points to the base address. */
|
||||
add r23, r0, r7 /* Move reloc addr to r23 */
|
||||
addi r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
|
||||
rsub r23, r24, r23 /* keep - this is already here gd->reloc_off */
|
||||
rsub r23, r21, r7 /* keep - this is already here gd->reloc_off */
|
||||
|
||||
/* Setup vectors with post-relocation symbols */
|
||||
add r5, r0, r23 /* load gd->reloc_off to r5 */
|
||||
bralid r15, __setup_exceptions
|
||||
brlid r15, __setup_exceptions
|
||||
nop
|
||||
|
||||
#if defined(CONFIG_STATIC_RELA)
|
||||
/* reloc_offset is current location */
|
||||
SYM_ADDR(r10, r0, _start)
|
||||
|
||||
/* r5 new address where I should copy code */
|
||||
add r5, r0, r7 /* Move reloc addr to r5 */
|
||||
|
||||
/* Verbose message */
|
||||
addi r6, r0, 0
|
||||
|
||||
SYM_ADDR(r7, r0, __rel_dyn_start)
|
||||
rsub r7, r10, r7
|
||||
add r7, r7, r5
|
||||
SYM_ADDR(r8, r0, __rel_dyn_end)
|
||||
rsub r8, r10, r8
|
||||
add r8, r8, r5
|
||||
SYM_ADDR(r9, r0, __dyn_sym_start)
|
||||
rsub r9, r10, r9
|
||||
add r9, r9, r5
|
||||
brlid r15, mb_fix_rela
|
||||
nop
|
||||
|
||||
/* end of code which does relocation */
|
||||
#else
|
||||
/* Check if GOT exist */
|
||||
addik r21, r23, _got_start
|
||||
addik r22, r23, _got_end
|
||||
|
@ -309,21 +351,15 @@ relocate_code:
|
|||
cmpu r12, r21, r22 /* Check if this cross boundary */
|
||||
bneid r12, 3b
|
||||
addik r21. r21, 4
|
||||
|
||||
/* Update pointer to GOT */
|
||||
mfs r20, rpc
|
||||
addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
|
||||
addk r20, r20, r23
|
||||
#endif
|
||||
|
||||
/* Flush caches to ensure consistency */
|
||||
addik r5, r0, 0
|
||||
addik r6, r0, XILINX_DCACHE_BYTE_SIZE
|
||||
bralid r15, flush_cache
|
||||
brlid r15, flush_cache_all
|
||||
nop
|
||||
|
||||
2: addi r5, r31, 0 /* gd is initialized in board_r.c */
|
||||
addi r6, r0, CONFIG_SYS_TEXT_BASE
|
||||
addi r12, r23, board_init_r
|
||||
SYM_ADDR(r6, r0, _start)
|
||||
SYM_ADDR(r12, r23, board_init_r)
|
||||
bra r12 /* Jump to relocated code */
|
||||
|
||||
.end relocate_code
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2007 Michal Simek
|
||||
*
|
||||
* Michal SIMEK <monstr@monstr.eu>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <init.h>
|
||||
#include <log.h>
|
||||
#include <time.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/microblaze_timer.h>
|
||||
#include <asm/microblaze_intc.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
volatile int timestamp = 0;
|
||||
microblaze_timer_t *tmr;
|
||||
|
||||
ulong get_timer (ulong base)
|
||||
{
|
||||
if (tmr)
|
||||
return timestamp - base;
|
||||
return timestamp++ - base;
|
||||
}
|
||||
|
||||
void __udelay(unsigned long usec)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
if (tmr) {
|
||||
i = get_timer(0);
|
||||
while ((get_timer(0) - i) < (usec / 1000))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
static void timer_isr(void *arg)
|
||||
{
|
||||
timestamp++;
|
||||
tmr->control = tmr->control | TIMER_INTERRUPT;
|
||||
}
|
||||
|
||||
int timer_init (void)
|
||||
{
|
||||
int irq = -1;
|
||||
u32 preload = 0;
|
||||
u32 ret = 0;
|
||||
const void *blob = gd->fdt_blob;
|
||||
int node = 0;
|
||||
u32 cell[2];
|
||||
|
||||
debug("TIMER: Initialization\n");
|
||||
|
||||
/* Do not init before relocation */
|
||||
if (!(gd->flags & GD_FLG_RELOC))
|
||||
return 0;
|
||||
|
||||
node = fdt_node_offset_by_compatible(blob, node,
|
||||
"xlnx,xps-timer-1.00.a");
|
||||
if (node != -1) {
|
||||
fdt_addr_t base = fdtdec_get_addr(blob, node, "reg");
|
||||
if (base == FDT_ADDR_T_NONE)
|
||||
return -1;
|
||||
|
||||
debug("TIMER: Base addr %lx\n", base);
|
||||
tmr = (microblaze_timer_t *)base;
|
||||
|
||||
ret = fdtdec_get_int_array(blob, node, "interrupts",
|
||||
cell, ARRAY_SIZE(cell));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
irq = cell[0];
|
||||
debug("TIMER: IRQ %x\n", irq);
|
||||
|
||||
preload = fdtdec_get_int(blob, node, "clock-frequency", 0);
|
||||
preload /= CONFIG_SYS_HZ;
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (tmr && preload && irq >= 0) {
|
||||
tmr->loadreg = preload;
|
||||
tmr->control = TIMER_INTERRUPT | TIMER_RESET;
|
||||
tmr->control = TIMER_ENABLE | TIMER_ENABLE_INTR |\
|
||||
TIMER_RELOAD | TIMER_DOWN_COUNT;
|
||||
timestamp = 0;
|
||||
ret = install_interrupt_handler (irq, timer_isr, (void *)tmr);
|
||||
if (ret)
|
||||
tmr = NULL;
|
||||
}
|
||||
/* No problem if timer is not found/initialized */
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int timer_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function is derived from PowerPC code (read timebase as long long).
|
||||
* On Microblaze it just returns the timer value.
|
||||
*/
|
||||
unsigned long long get_ticks(void)
|
||||
{
|
||||
return get_timer(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is derived from PowerPC code (timebase clock frequency).
|
||||
* On Microblaze it returns the number of timer ticks per second.
|
||||
*/
|
||||
ulong get_tbclk(void)
|
||||
{
|
||||
return CONFIG_SYS_HZ;
|
||||
}
|
|
@ -46,6 +46,20 @@ SECTIONS
|
|||
}
|
||||
__init_end = . ;
|
||||
|
||||
. = ALIGN(4);
|
||||
__rel_dyn_start = .;
|
||||
.rela.dyn : {
|
||||
*(.rela.dyn)
|
||||
}
|
||||
__rel_dyn_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
__dyn_sym_start = .;
|
||||
.dynsym : {
|
||||
*(.dynsym)
|
||||
}
|
||||
__dyn_sym_end = .;
|
||||
|
||||
.bss ALIGN(0x4):
|
||||
{
|
||||
__bss_start = .;
|
||||
|
|
|
@ -18,4 +18,9 @@
|
|||
#define ARCH_DMA_MINALIGN 16
|
||||
#endif
|
||||
|
||||
/**
|
||||
* flush_cache_all - flush the entire instruction/data caches
|
||||
*/
|
||||
void flush_cache_all(void);
|
||||
|
||||
#endif /* __MICROBLAZE_CACHE_H__ */
|
||||
|
|
114
arch/microblaze/include/asm/cpuinfo.h
Normal file
114
arch/microblaze/include/asm/cpuinfo.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2022, Ovidiu Panait <ovpanait@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MICROBLAZE_CPUINFO_H
|
||||
#define __ASM_MICROBLAZE_CPUINFO_H
|
||||
|
||||
/**
|
||||
* struct microblaze_cpuinfo - CPU info for microblaze processor core.
|
||||
*
|
||||
* @icache_size: Size of instruction cache memory in bytes.
|
||||
* @icache_line_length: Instruction cache line length in bytes.
|
||||
* @dcache_size: Size of data cache memory in bytes.
|
||||
* @dcache_line_length: Data cache line length in bytes.
|
||||
* @use_mmu: MMU support flag.
|
||||
* @cpu_freq: Cpu clock frequency in Hz.
|
||||
* @addr_size: Address bus width in bits.
|
||||
* @ver_code: Cpu version code.
|
||||
* @fpga_code: FPGA family version code.
|
||||
*/
|
||||
struct microblaze_cpuinfo {
|
||||
u32 icache_size;
|
||||
u32 icache_line_length;
|
||||
|
||||
u32 dcache_size;
|
||||
u32 dcache_line_length;
|
||||
|
||||
#if CONFIG_IS_ENABLED(CPU_MICROBLAZE)
|
||||
u32 use_mmu;
|
||||
u32 cpu_freq;
|
||||
u32 addr_size;
|
||||
|
||||
u32 ver_code;
|
||||
u32 fpga_code;
|
||||
#endif /* CONFIG_CPU_MICROBLAZE */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct microblaze_version_data - Maps a hex version code to a cpu/fpga name.
|
||||
*/
|
||||
struct microblaze_version_map {
|
||||
const char *string;
|
||||
const u32 code;
|
||||
};
|
||||
|
||||
/**
|
||||
* microblaze_lookup_cpu_version_code() - Get hex version code for the
|
||||
* specified cpu name string.
|
||||
*
|
||||
* This function searches the cpu_ver_lookup[] array for the hex version code
|
||||
* associated with a specific CPU name. The version code is returned if a match
|
||||
* is found, otherwise 0.
|
||||
*
|
||||
* @string: cpu name string
|
||||
*
|
||||
* Return: >0 if the entry is found, 0 otherwise.
|
||||
*/
|
||||
const u32 microblaze_lookup_cpu_version_code(const char *string);
|
||||
|
||||
/**
|
||||
* microblaze_lookup_fpga_family_code() - Get hex version code for the
|
||||
* specified fpga family name.
|
||||
*
|
||||
* This function searches the family_string_lookup[] array for the hex version
|
||||
* code associated with a specific fpga family name. The version code is
|
||||
* returned if a match is found, otherwise 0.
|
||||
*
|
||||
* @string: fpga family name string
|
||||
*
|
||||
* Return: >0 if the entry is found, 0 otherwise.
|
||||
*/
|
||||
const u32 microblaze_lookup_fpga_family_code(const char *string);
|
||||
|
||||
/**
|
||||
* microblaze_lookup_cpu_version_string() - Get cpu name for the specified cpu
|
||||
* version code.
|
||||
*
|
||||
* This function searches the cpu_ver_lookup[] array for the cpu name string
|
||||
* associated with a specific version code. The cpu name is returned if a match
|
||||
* is found, otherwise "(unknown)".
|
||||
*
|
||||
* @code: cpu version code
|
||||
*
|
||||
* Return: Pointer to the cpu name if the entry is found, otherwise "(unknown)".
|
||||
*/
|
||||
const char *microblaze_lookup_cpu_version_string(const u32 code);
|
||||
|
||||
/**
|
||||
* microblaze_lookup_fpga_family_string() - Get fpga family name for the
|
||||
* specified version code.
|
||||
*
|
||||
* This function searches the family_string_lookup[] array for the fpga family
|
||||
* name string associated with a specific version code. The fpga family name is
|
||||
* returned if a match is found, otherwise "(unknown)".
|
||||
*
|
||||
* @code: fpga family version code
|
||||
*
|
||||
* Return: Pointer to the fpga family name if the entry is found, otherwise
|
||||
* "(unknown)".
|
||||
*/
|
||||
const char *microblaze_lookup_fpga_family_string(const u32 code);
|
||||
|
||||
/**
|
||||
* microblaze_early_cpuinfo_init() - Initialize cpuinfo with default values.
|
||||
*
|
||||
* Initializes the global data cpuinfo structure with default values (cache
|
||||
* size, cache line size, etc.). It is called very early in the boot process
|
||||
* (start.S codepath right before the first cache flush call) to ensure that
|
||||
* cache related operations are properly handled.
|
||||
*/
|
||||
void microblaze_early_cpuinfo_init(void);
|
||||
|
||||
#endif /* __ASM_MICROBLAZE_CPUINFO_H */
|
|
@ -8,12 +8,17 @@
|
|||
#ifndef __ASM_GBL_DATA_H
|
||||
#define __ASM_GBL_DATA_H
|
||||
|
||||
#include <asm/cpuinfo.h>
|
||||
|
||||
/* Architecture-specific global data */
|
||||
struct arch_global_data {
|
||||
struct microblaze_cpuinfo cpuinfo;
|
||||
};
|
||||
|
||||
#include <asm-generic/global_data.h>
|
||||
|
||||
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r31")
|
||||
|
||||
#define gd_cpuinfo() ((struct microblaze_cpuinfo *)&gd->arch.cpuinfo)
|
||||
|
||||
#endif /* __ASM_GBL_DATA_H */
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2007 Michal Simek
|
||||
*
|
||||
* Michal SIMEK <monstr@monstr.cz>
|
||||
*/
|
||||
|
||||
#include <irq_func.h>
|
||||
|
||||
typedef volatile struct microblaze_intc_t {
|
||||
int isr; /* interrupt status register */
|
||||
int ipr; /* interrupt pending register */
|
||||
int ier; /* interrupt enable register */
|
||||
int iar; /* interrupt acknowledge register */
|
||||
int sie; /* set interrupt enable bits */
|
||||
int cie; /* clear interrupt enable bits */
|
||||
int ivr; /* interrupt vector register */
|
||||
int mer; /* master enable register */
|
||||
} microblaze_intc_t;
|
||||
|
||||
struct irq_action {
|
||||
interrupt_handler_t *handler; /* pointer to interrupt rutine */
|
||||
void *arg;
|
||||
int count; /* number of interrupt */
|
||||
};
|
||||
|
||||
/**
|
||||
* Register and unregister interrupt handler rutines
|
||||
*
|
||||
* @param irq IRQ number
|
||||
* @param hdlr Interrupt handler rutine
|
||||
* @param arg Pointer to argument which is passed to int. handler rutine
|
||||
* Return: 0 if registration pass, 1 if unregistration pass,
|
||||
* or an error code < 0 otherwise
|
||||
*/
|
||||
int install_interrupt_handler(int irq, interrupt_handler_t *hdlr,
|
||||
void *arg);
|
|
@ -1,26 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2007 Michal Simek
|
||||
*
|
||||
* Michal SIMEK <monstr@monstr.cz>
|
||||
*/
|
||||
|
||||
#define TIMER_ENABLE_ALL 0x400 /* ENALL */
|
||||
#define TIMER_PWM 0x200 /* PWMA0 */
|
||||
#define TIMER_INTERRUPT 0x100 /* T0INT */
|
||||
#define TIMER_ENABLE 0x080 /* ENT0 */
|
||||
#define TIMER_ENABLE_INTR 0x040 /* ENIT0 */
|
||||
#define TIMER_RESET 0x020 /* LOAD0 */
|
||||
#define TIMER_RELOAD 0x010 /* ARHT0 */
|
||||
#define TIMER_EXT_CAPTURE 0x008 /* CAPT0 */
|
||||
#define TIMER_EXT_COMPARE 0x004 /* GENT0 */
|
||||
#define TIMER_DOWN_COUNT 0x002 /* UDT0 */
|
||||
#define TIMER_CAPTURE_MODE 0x001 /* MDT0 */
|
||||
|
||||
typedef volatile struct microblaze_timer_t {
|
||||
int control; /* control/statuc register TCSR */
|
||||
int loadreg; /* load register TLR */
|
||||
int counter; /* timer/counter register */
|
||||
} microblaze_timer_t;
|
||||
|
||||
int timer_init(void);
|
75
arch/microblaze/include/asm/pvr.h
Normal file
75
arch/microblaze/include/asm/pvr.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2022, Ovidiu Panait <ovpanait@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MICROBLAZE_PVR_H
|
||||
#define __ASM_MICROBLAZE_PVR_H
|
||||
|
||||
#include <asm/asm.h>
|
||||
|
||||
#define PVR_FULL_COUNT 13 /* PVR0 - PVR12 */
|
||||
|
||||
#define __get_pvr(val, reg) \
|
||||
__asm__ __volatile__ ("mfs %0," #reg : "=r" (val) :: "memory")
|
||||
#define get_pvr(pvrid, val) \
|
||||
__get_pvr(val, rpvr ## pvrid)
|
||||
|
||||
#define PVR_MSR_BIT 0x00000400
|
||||
|
||||
/* PVR0 masks */
|
||||
#define PVR0_PVR_FULL_MASK 0x80000000
|
||||
#define PVR0_VERSION_MASK 0x0000FF00
|
||||
|
||||
/* PVR4 masks - ICache configs */
|
||||
#define PVR4_ICACHE_LINE_LEN_MASK 0x00E00000 /* ICLL */
|
||||
#define PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000 /* ICBS */
|
||||
|
||||
/* PVR5 masks - DCache configs */
|
||||
#define PVR5_DCACHE_LINE_LEN_MASK 0x00E00000 /* DCLL */
|
||||
#define PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000 /* DCBS */
|
||||
|
||||
/* PVR10 masks - FPGA family */
|
||||
#define PVR10_TARGET_FAMILY_MASK 0xFF000000
|
||||
|
||||
/* PVR11 masks - MMU */
|
||||
#define PVR11_USE_MMU 0xC0000000
|
||||
|
||||
/* PVR access macros */
|
||||
#define PVR_VERSION(pvr) \
|
||||
((pvr[0] & PVR0_VERSION_MASK) >> 8)
|
||||
|
||||
#define PVR_ICACHE_LINE_LEN(pvr) \
|
||||
((1 << ((pvr[4] & PVR4_ICACHE_LINE_LEN_MASK) >> 21)) << 2)
|
||||
#define PVR_ICACHE_BYTE_SIZE(pvr) \
|
||||
(1 << ((pvr[4] & PVR4_ICACHE_BYTE_SIZE_MASK) >> 16))
|
||||
|
||||
#define PVR_DCACHE_LINE_LEN(pvr) \
|
||||
((1 << ((pvr[5] & PVR5_DCACHE_LINE_LEN_MASK) >> 21)) << 2)
|
||||
#define PVR_DCACHE_BYTE_SIZE(pvr) \
|
||||
(1 << ((pvr[5] & PVR5_DCACHE_BYTE_SIZE_MASK) >> 16))
|
||||
|
||||
#define PVR_USE_MMU(pvr) \
|
||||
((pvr[11] & PVR11_USE_MMU) >> 30)
|
||||
|
||||
#define PVR_TARGET_FAMILY(pvr) \
|
||||
((pvr[10] & PVR10_TARGET_FAMILY_MASK) >> 24)
|
||||
|
||||
/**
|
||||
* microblaze_cpu_has_pvr_full() - Check for full PVR support
|
||||
*
|
||||
* Check MSR register for PVR support and, if applicable, check the PVR0
|
||||
* register for full PVR support.
|
||||
*
|
||||
* Return: 1 if there is full PVR support, 0 otherwise.
|
||||
*/
|
||||
int microblaze_cpu_has_pvr_full(void);
|
||||
|
||||
/**
|
||||
* microblaze_get_all_pvrs() - Copy PVR0-PVR12 to destination array
|
||||
*
|
||||
* @pvr: destination array of size PVR_FULL_COUNT
|
||||
*/
|
||||
void microblaze_get_all_pvrs(u32 pvr[PVR_FULL_COUNT]);
|
||||
|
||||
#endif /* __ASM_MICROBLAZE_PVR_H */
|
|
@ -57,9 +57,7 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
|
|||
"(fake run for tracing)" : "");
|
||||
bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
|
||||
|
||||
#ifdef XILINX_USE_DCACHE
|
||||
flush_cache(0, XILINX_DCACHE_BYTE_SIZE);
|
||||
#endif
|
||||
flush_cache_all();
|
||||
|
||||
if (!fake) {
|
||||
/*
|
||||
|
|
|
@ -180,24 +180,6 @@ source "arch/mips/mach-octeon/Kconfig"
|
|||
|
||||
if MIPS
|
||||
|
||||
choice
|
||||
prompt "Endianness selection"
|
||||
help
|
||||
Some MIPS boards can be configured for either little or big endian
|
||||
byte order. These modes require different U-Boot images. In general there
|
||||
is one preferred byteorder for a particular system but some systems are
|
||||
just as commonly used in the one or the other endianness.
|
||||
|
||||
config SYS_BIG_ENDIAN
|
||||
bool "Big endian"
|
||||
depends on SUPPORTS_BIG_ENDIAN
|
||||
|
||||
config SYS_LITTLE_ENDIAN
|
||||
bool "Little endian"
|
||||
depends on SUPPORTS_LITTLE_ENDIAN
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "CPU selection"
|
||||
default CPU_MIPS32_R2
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
#
|
||||
|
||||
obj-y += board.o
|
||||
ifndef CONFIG_ARCH_ZYNQ
|
||||
obj-$(CONFIG_DISPLAY_CPUINFO) += cpu-info.o
|
||||
endif
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_CMD_FRU) += fru.o fru_ops.o
|
||||
endif
|
||||
|
|
|
@ -485,31 +485,6 @@ int __maybe_unused board_fit_config_name_match(const char *name)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DISPLAY_CPUINFO) && !defined(CONFIG_ARCH_ZYNQ)
|
||||
int print_cpuinfo(void)
|
||||
{
|
||||
struct udevice *soc;
|
||||
char name[SOC_MAX_STR_SIZE];
|
||||
int ret;
|
||||
|
||||
ret = soc_get(&soc);
|
||||
if (ret) {
|
||||
printf("CPU: UNKNOWN\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = soc_get_family(soc, name, SOC_MAX_STR_SIZE);
|
||||
if (ret)
|
||||
printf("CPU: %s\n", name);
|
||||
|
||||
ret = soc_get_revision(soc, name, SOC_MAX_STR_SIZE);
|
||||
if (ret)
|
||||
printf("Silicon: %s\n", name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_IS_ENABLED(DTB_RESELECT)
|
||||
#define MAX_NAME_LENGTH 50
|
||||
|
||||
|
|
35
board/xilinx/common/cpu-info.c
Normal file
35
board/xilinx/common/cpu-info.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2014 - 2020 Xilinx, Inc.
|
||||
* Michal Simek <michal.simek@xilinx.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <soc.h>
|
||||
|
||||
int print_cpuinfo(void)
|
||||
{
|
||||
struct udevice *soc;
|
||||
char name[SOC_MAX_STR_SIZE];
|
||||
int ret;
|
||||
|
||||
ret = soc_get(&soc);
|
||||
if (ret) {
|
||||
printf("CPU: UNKNOWN\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = soc_get_family(soc, name, SOC_MAX_STR_SIZE);
|
||||
if (ret)
|
||||
printf("CPU: %s\n", name);
|
||||
|
||||
ret = soc_get_revision(soc, name, SOC_MAX_STR_SIZE);
|
||||
if (ret)
|
||||
printf("Silicon: %s\n", name);
|
||||
|
||||
ret = soc_get_machine(soc, name, SOC_MAX_STR_SIZE);
|
||||
if (ret)
|
||||
printf("Chip: %s\n", name);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -38,6 +38,14 @@ config XILINX_MICROBLAZE0_HW_VER
|
|||
string "Core version number"
|
||||
default "7.10.d"
|
||||
|
||||
config XILINX_MICROBLAZE0_FPGA_FAMILY
|
||||
string "Targeted FPGA family"
|
||||
default "virtex5"
|
||||
help
|
||||
This option contains info about the target FPGA architecture
|
||||
(Zynq-7000, UltraScale+ Kintex, etc) that the MicroBlaze soft core is
|
||||
implemented on. It corresponds to the C_FAMILY hdl parameter.
|
||||
|
||||
config XILINX_MICROBLAZE0_USR_EXCEP
|
||||
bool "MicroBlaze user exception support"
|
||||
default y
|
||||
|
@ -63,4 +71,50 @@ config XILINX_MICROBLAZE0_VECTOR_BASE_ADDR
|
|||
Memory address location of the exception vector table. It is
|
||||
configurable via the C_BASE_VECTORS hdl parameter.
|
||||
|
||||
config XILINX_MICROBLAZE0_USE_WDC
|
||||
bool "MicroBlaze wdc instruction support"
|
||||
default y
|
||||
help
|
||||
Enable this option if the MicroBlaze processor is configured with
|
||||
support for the "wdc" (Write to Data Cache) instruction.
|
||||
|
||||
config SPL_XILINX_MICROBLAZE0_USE_WDC
|
||||
bool
|
||||
default XILINX_MICROBLAZE0_USE_WDC
|
||||
|
||||
config XILINX_MICROBLAZE0_USE_WIC
|
||||
bool "MicroBlaze wic instruction support"
|
||||
default y
|
||||
help
|
||||
Enable this option if the MicroBlaze processor is configured with
|
||||
support for the "wic" (Write to Instruction Cache) instruction.
|
||||
|
||||
config SPL_XILINX_MICROBLAZE0_USE_WIC
|
||||
bool
|
||||
default XILINX_MICROBLAZE0_USE_WIC
|
||||
|
||||
config XILINX_MICROBLAZE0_DCACHE_SIZE
|
||||
int "Default data cache size"
|
||||
default 32768
|
||||
help
|
||||
This fallback size will be used when no dcache info can be found in
|
||||
the device tree, or when the data cache is flushed very early in the
|
||||
boot process, before device tree is available.
|
||||
|
||||
config XILINX_MICROBLAZE0_ICACHE_SIZE
|
||||
int "Default instruction cache size"
|
||||
default 32768
|
||||
help
|
||||
This fallback size will be used when no icache info can be found in
|
||||
the device tree, or when the instruction cache is flushed very early
|
||||
in the boot process, before device tree is available.
|
||||
|
||||
config XILINX_MICROBLAZE0_PVR
|
||||
bool "MicroBlaze PVR support"
|
||||
help
|
||||
Enables helper functions and macros needed to manipulate PVR
|
||||
(Processor Version Register) data. Currently, only the microblaze
|
||||
UCLASS_CPU driver makes use of this feature to retrieve CPU info at
|
||||
runtime.
|
||||
|
||||
endif
|
||||
|
|
|
@ -91,6 +91,23 @@ int board_early_init_r(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (current_el() > 1) {
|
||||
smp_kick_all_cpus();
|
||||
dcache_disable();
|
||||
armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry,
|
||||
ES_TO_AARCH64);
|
||||
} else {
|
||||
printf("FAIL: current EL is not above EL1\n");
|
||||
ret = EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 versal_get_bootmode(void)
|
||||
{
|
||||
u8 bootmode;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -19,6 +19,7 @@
|
|||
#include <sata.h>
|
||||
#include <ahci.h>
|
||||
#include <scsi.h>
|
||||
#include <soc.h>
|
||||
#include <malloc.h>
|
||||
#include <memalign.h>
|
||||
#include <wdt.h>
|
||||
|
@ -44,278 +45,10 @@
|
|||
|
||||
#include "pm_cfg_obj.h"
|
||||
|
||||
#define ZYNQMP_VERSION_SIZE 7
|
||||
#define EFUSE_VCU_DIS_MASK 0x100
|
||||
#define EFUSE_VCU_DIS_SHIFT 8
|
||||
#define EFUSE_GPU_DIS_MASK 0x20
|
||||
#define EFUSE_GPU_DIS_SHIFT 5
|
||||
#define IDCODE2_PL_INIT_MASK 0x200
|
||||
#define IDCODE2_PL_INIT_SHIFT 9
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if CONFIG_IS_ENABLED(FPGA) && defined(CONFIG_FPGA_ZYNQMPPL)
|
||||
static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
|
||||
|
||||
enum {
|
||||
ZYNQMP_VARIANT_EG = BIT(0U),
|
||||
ZYNQMP_VARIANT_EV = BIT(1U),
|
||||
ZYNQMP_VARIANT_CG = BIT(2U),
|
||||
ZYNQMP_VARIANT_DR = BIT(3U),
|
||||
};
|
||||
|
||||
static const struct {
|
||||
u32 id;
|
||||
u8 device;
|
||||
u8 variants;
|
||||
} zynqmp_devices[] = {
|
||||
{
|
||||
.id = 0x04688093,
|
||||
.device = 1,
|
||||
.variants = ZYNQMP_VARIANT_EG,
|
||||
},
|
||||
{
|
||||
.id = 0x04711093,
|
||||
.device = 2,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
|
||||
},
|
||||
{
|
||||
.id = 0x04710093,
|
||||
.device = 3,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
|
||||
},
|
||||
{
|
||||
.id = 0x04721093,
|
||||
.device = 4,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG |
|
||||
ZYNQMP_VARIANT_EV,
|
||||
},
|
||||
{
|
||||
.id = 0x04720093,
|
||||
.device = 5,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG |
|
||||
ZYNQMP_VARIANT_EV,
|
||||
},
|
||||
{
|
||||
.id = 0x04739093,
|
||||
.device = 6,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
|
||||
},
|
||||
{
|
||||
.id = 0x04730093,
|
||||
.device = 7,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG |
|
||||
ZYNQMP_VARIANT_EV,
|
||||
},
|
||||
{
|
||||
.id = 0x04738093,
|
||||
.device = 9,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
|
||||
},
|
||||
{
|
||||
.id = 0x04740093,
|
||||
.device = 11,
|
||||
.variants = ZYNQMP_VARIANT_EG,
|
||||
},
|
||||
{
|
||||
.id = 0x04750093,
|
||||
.device = 15,
|
||||
.variants = ZYNQMP_VARIANT_EG,
|
||||
},
|
||||
{
|
||||
.id = 0x04759093,
|
||||
.device = 17,
|
||||
.variants = ZYNQMP_VARIANT_EG,
|
||||
},
|
||||
{
|
||||
.id = 0x04758093,
|
||||
.device = 19,
|
||||
.variants = ZYNQMP_VARIANT_EG,
|
||||
},
|
||||
{
|
||||
.id = 0x047E1093,
|
||||
.device = 21,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047E3093,
|
||||
.device = 23,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047E5093,
|
||||
.device = 25,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047E4093,
|
||||
.device = 27,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047E0093,
|
||||
.device = 28,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047E2093,
|
||||
.device = 29,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047E6093,
|
||||
.device = 39,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047FD093,
|
||||
.device = 43,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047F8093,
|
||||
.device = 46,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047FF093,
|
||||
.device = 47,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047FB093,
|
||||
.device = 48,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047FE093,
|
||||
.device = 49,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x046d0093,
|
||||
.device = 67,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct {
|
||||
u32 id;
|
||||
char *name;
|
||||
} zynqmp_svd_devices[] = {
|
||||
{
|
||||
.id = 0x04714093,
|
||||
.name = "xck24"
|
||||
},
|
||||
{
|
||||
.id = 0x04724093,
|
||||
.name = "xck26",
|
||||
},
|
||||
};
|
||||
|
||||
static char *zynqmp_detect_svd_name(u32 idcode)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(zynqmp_svd_devices); i++) {
|
||||
if (zynqmp_svd_devices[i].id == (idcode & 0x0FFFFFFF))
|
||||
return zynqmp_svd_devices[i].name;
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static char *zynqmp_get_silicon_idcode_name(void)
|
||||
{
|
||||
u32 i;
|
||||
u32 idcode, idcode2;
|
||||
char name[ZYNQMP_VERSION_SIZE];
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
|
||||
ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
|
||||
if (ret) {
|
||||
debug("%s: Getting chipid failed\n", __func__);
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/*
|
||||
* Firmware returns:
|
||||
* payload[0][31:0] = status of the operation
|
||||
* payload[1]] = IDCODE
|
||||
* payload[2][19:0] = Version
|
||||
* payload[2][28:20] = EXTENDED_IDCODE
|
||||
* payload[2][29] = PL_INIT
|
||||
*/
|
||||
|
||||
idcode = ret_payload[1];
|
||||
idcode2 = ret_payload[2] >> ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
|
||||
debug("%s, IDCODE: 0x%0x, IDCODE2: 0x%0x\r\n", __func__, idcode,
|
||||
idcode2);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
|
||||
if (zynqmp_devices[i].id == (idcode & 0x0FFFFFFF))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= ARRAY_SIZE(zynqmp_devices))
|
||||
return zynqmp_detect_svd_name(idcode);
|
||||
|
||||
/* Add device prefix to the name */
|
||||
ret = snprintf(name, ZYNQMP_VERSION_SIZE, "zu%d",
|
||||
zynqmp_devices[i].device);
|
||||
if (ret < 0)
|
||||
return "unknown";
|
||||
|
||||
if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_EV) {
|
||||
/* Devices with EV variant might be EG/CG/EV family */
|
||||
if (idcode2 & IDCODE2_PL_INIT_MASK) {
|
||||
u32 family = ((idcode2 & EFUSE_VCU_DIS_MASK) >>
|
||||
EFUSE_VCU_DIS_SHIFT) << 1 |
|
||||
((idcode2 & EFUSE_GPU_DIS_MASK) >>
|
||||
EFUSE_GPU_DIS_SHIFT);
|
||||
|
||||
/*
|
||||
* Get family name based on extended idcode values as
|
||||
* determined on UG1087, EXTENDED_IDCODE register
|
||||
* description
|
||||
*/
|
||||
switch (family) {
|
||||
case 0x00:
|
||||
strncat(name, "ev", 2);
|
||||
break;
|
||||
case 0x10:
|
||||
strncat(name, "eg", 2);
|
||||
break;
|
||||
case 0x11:
|
||||
strncat(name, "cg", 2);
|
||||
break;
|
||||
default:
|
||||
/* Do not append family name*/
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* When PL powered down the VCU Disable efuse cannot be
|
||||
* read. So, ignore the bit and just findout if it is CG
|
||||
* or EG/EV variant.
|
||||
*/
|
||||
strncat(name, (idcode2 & EFUSE_GPU_DIS_MASK) ? "cg" :
|
||||
"e", 2);
|
||||
}
|
||||
} else if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_CG) {
|
||||
/* Devices with CG variant might be EG or CG family */
|
||||
strncat(name, (idcode2 & EFUSE_GPU_DIS_MASK) ? "cg" : "eg", 2);
|
||||
} else if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_EG) {
|
||||
strncat(name, "eg", 2);
|
||||
} else if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_DR) {
|
||||
strncat(name, "dr", 2);
|
||||
} else {
|
||||
debug("Variant not identified\n");
|
||||
}
|
||||
|
||||
return strdup(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
int __maybe_unused psu_uboot_init(void)
|
||||
|
@ -406,6 +139,11 @@ static void print_secure_boot(void)
|
|||
|
||||
int board_init(void)
|
||||
{
|
||||
#if CONFIG_IS_ENABLED(FPGA) && defined(CONFIG_FPGA_ZYNQMPPL)
|
||||
struct udevice *soc;
|
||||
char name[SOC_MAX_STR_SIZE];
|
||||
int ret;
|
||||
#endif
|
||||
#if defined(CONFIG_ZYNQMP_FIRMWARE)
|
||||
struct udevice *dev;
|
||||
|
||||
|
@ -432,10 +170,15 @@ int board_init(void)
|
|||
printf("EL Level:\tEL%d\n", current_el());
|
||||
|
||||
#if CONFIG_IS_ENABLED(FPGA) && defined(CONFIG_FPGA_ZYNQMPPL)
|
||||
zynqmppl.name = zynqmp_get_silicon_idcode_name();
|
||||
printf("Chip ID:\t%s\n", zynqmppl.name);
|
||||
fpga_init();
|
||||
fpga_add(fpga_xilinx, &zynqmppl);
|
||||
ret = soc_get(&soc);
|
||||
if (!ret) {
|
||||
ret = soc_get_machine(soc, name, sizeof(name));
|
||||
if (ret >= 0) {
|
||||
zynqmppl.name = strdup(name);
|
||||
fpga_init();
|
||||
fpga_add(fpga_xilinx, &zynqmppl);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* display secure boot information */
|
||||
|
@ -924,6 +667,7 @@ void set_dfu_alt_info(char *interface, char *devstr)
|
|||
bootseq, multiboot, bootseq,
|
||||
CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, bootseq);
|
||||
break;
|
||||
#if defined(CONFIG_SYS_SPI_U_BOOT_OFFS)
|
||||
case QSPI_MODE_24BIT:
|
||||
case QSPI_MODE_32BIT:
|
||||
snprintf(buf, DFU_ALT_BUF_LEN,
|
||||
|
@ -932,6 +676,7 @@ void set_dfu_alt_info(char *interface, char *devstr)
|
|||
multiboot * SZ_32K, CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
|
||||
CONFIG_SYS_SPI_U_BOOT_OFFS);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
|
39
cmd/cpu.c
39
cmd/cpu.c
|
@ -82,36 +82,13 @@ static int do_cpu_detail(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct cmd_tbl cmd_cpu_sub[] = {
|
||||
U_BOOT_CMD_MKENT(list, 2, 1, do_cpu_list, "", ""),
|
||||
U_BOOT_CMD_MKENT(detail, 4, 0, do_cpu_detail, "", ""),
|
||||
};
|
||||
|
||||
/*
|
||||
* Process a cpu sub-command
|
||||
*/
|
||||
static int do_cpu(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
struct cmd_tbl *c = NULL;
|
||||
|
||||
/* Strip off leading 'cpu' command argument */
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (argc)
|
||||
c = find_cmd_tbl(argv[0], cmd_cpu_sub,
|
||||
ARRAY_SIZE(cmd_cpu_sub));
|
||||
|
||||
if (c)
|
||||
return c->cmd(cmdtp, flag, argc, argv);
|
||||
else
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
cpu, 2, 1, do_cpu,
|
||||
"display information about CPUs",
|
||||
#if CONFIG_IS_ENABLED(SYS_LONGHELP)
|
||||
static char cpu_help_text[] =
|
||||
"list - list available CPUs\n"
|
||||
"cpu detail - show CPU detail"
|
||||
);
|
||||
;
|
||||
#endif
|
||||
|
||||
U_BOOT_CMD_WITH_SUBCMDS(cpu, "display information about CPUs", cpu_help_text,
|
||||
U_BOOT_SUBCMD_MKENT(list, 1, 1, do_cpu_list),
|
||||
U_BOOT_SUBCMD_MKENT(detail, 1, 0, do_cpu_detail));
|
||||
|
|
|
@ -684,6 +684,8 @@ static int setup_reloc(void)
|
|||
#ifdef CONFIG_SYS_TEXT_BASE
|
||||
#ifdef ARM
|
||||
gd->reloc_off = gd->relocaddr - (unsigned long)__image_copy_start;
|
||||
#elif defined(CONFIG_MICROBLAZE)
|
||||
gd->reloc_off = gd->relocaddr - (u32)_start;
|
||||
#elif defined(CONFIG_M68K)
|
||||
/*
|
||||
* On all ColdFire arch cpu, monitor code starts always
|
||||
|
|
|
@ -14,6 +14,7 @@ CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1
|
|||
CONFIG_XILINX_MICROBLAZE0_USE_DIV=1
|
||||
CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=1
|
||||
CONFIG_DISTRO_DEFAULTS=y
|
||||
CONFIG_REMAKE_ELF=y
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_VERBOSE=y
|
||||
CONFIG_BOOTDELAY=-1
|
||||
|
@ -84,6 +85,7 @@ CONFIG_PHY_NATSEMI=y
|
|||
CONFIG_PHY_REALTEK=y
|
||||
CONFIG_PHY_VITESSE=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_DM_ETH_PHY=y
|
||||
CONFIG_XILINX_AXIEMAC=y
|
||||
CONFIG_XILINX_EMACLITE=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
|
|
|
@ -46,6 +46,7 @@ CONFIG_CMD_EFIDEBUG=y
|
|||
CONFIG_CMD_TIME=y
|
||||
CONFIG_CMD_TIMER=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_CMD_SQUASHFS=y
|
||||
CONFIG_CMD_MTDPARTS=y
|
||||
CONFIG_CMD_UBI=y
|
||||
CONFIG_PARTITION_TYPE_GUID=y
|
||||
|
@ -94,6 +95,7 @@ CONFIG_PHY_REALTEK=y
|
|||
CONFIG_PHY_TI_DP83867=y
|
||||
CONFIG_PHY_VITESSE=y
|
||||
CONFIG_PHY_FIXED=y
|
||||
CONFIG_DM_ETH_PHY=y
|
||||
CONFIG_PHY_GIGE=y
|
||||
CONFIG_XILINX_AXIEMAC=y
|
||||
CONFIG_XILINX_AXIMRMAC=y
|
||||
|
|
|
@ -71,6 +71,7 @@ CONFIG_CMD_EFIDEBUG=y
|
|||
CONFIG_CMD_TIME=y
|
||||
CONFIG_CMD_TIMER=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_CMD_SQUASHFS=y
|
||||
CONFIG_CMD_MTDPARTS=y
|
||||
CONFIG_CMD_MTDPARTS_SPREAD=y
|
||||
CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES=y
|
||||
|
@ -124,6 +125,7 @@ CONFIG_PHY_MICREL=y
|
|||
CONFIG_PHY_MICREL_KSZ90X1=y
|
||||
CONFIG_PHY_REALTEK=y
|
||||
CONFIG_PHY_XILINX=y
|
||||
CONFIG_DM_ETH_PHY=y
|
||||
CONFIG_MII=y
|
||||
CONFIG_ZYNQ_GEM=y
|
||||
CONFIG_ARM_DCC=y
|
||||
|
|
|
@ -94,6 +94,7 @@ CONFIG_CMD_TIMER=y
|
|||
CONFIG_CMD_REGULATOR=y
|
||||
CONFIG_CMD_TPM=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_CMD_SQUASHFS=y
|
||||
CONFIG_CMD_MTDPARTS=y
|
||||
CONFIG_CMD_MTDPARTS_SPREAD=y
|
||||
CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES=y
|
||||
|
@ -175,6 +176,7 @@ CONFIG_PHY_TI_DP83867=y
|
|||
CONFIG_PHY_VITESSE=y
|
||||
CONFIG_PHY_XILINX_GMII2RGMII=y
|
||||
CONFIG_PHY_FIXED=y
|
||||
CONFIG_DM_ETH_PHY=y
|
||||
CONFIG_XILINX_AXIEMAC=y
|
||||
CONFIG_ZYNQ_GEM=y
|
||||
CONFIG_DM_REGULATOR=y
|
||||
|
|
|
@ -328,13 +328,8 @@ static void *alloc_priv(int size, uint flags)
|
|||
* within this range at the start. The driver can then
|
||||
* use normal flush-after-write, invalidate-before-read
|
||||
* procedures.
|
||||
*
|
||||
* TODO(sjg@chromium.org): Drop this microblaze
|
||||
* exception.
|
||||
*/
|
||||
#ifndef CONFIG_MICROBLAZE
|
||||
flush_dcache_range((ulong)priv, (ulong)priv + size);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
priv = calloc(1, size);
|
||||
|
|
|
@ -19,3 +19,12 @@ config CPU_RISCV
|
|||
depends on CPU && RISCV
|
||||
help
|
||||
Support CPU cores for RISC-V architecture.
|
||||
|
||||
config CPU_MICROBLAZE
|
||||
bool "Enable Microblaze CPU driver"
|
||||
depends on CPU && MICROBLAZE
|
||||
select EVENT
|
||||
select DM_EVENT
|
||||
select XILINX_MICROBLAZE0_PVR
|
||||
help
|
||||
Support CPU cores for Microblaze architecture.
|
||||
|
|
|
@ -11,4 +11,5 @@ obj-$(CONFIG_ARCH_IMX8) += imx8_cpu.o
|
|||
obj-$(CONFIG_ARCH_AT91) += at91_cpu.o
|
||||
obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
|
||||
obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
|
||||
obj-$(CONFIG_CPU_MICROBLAZE) += microblaze_cpu.o
|
||||
obj-$(CONFIG_SANDBOX) += cpu_sandbox.o
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include <dm/lists.h>
|
||||
#include <dm/root.h>
|
||||
#include <linux/err.h>
|
||||
#include <relocate.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int cpu_probe_all(void)
|
||||
{
|
||||
|
@ -136,9 +139,36 @@ static int uclass_cpu_init(struct uclass *uc)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int uclass_cpu_post_bind(struct udevice *dev)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC) &&
|
||||
(gd->flags & GD_FLG_RELOC)) {
|
||||
struct cpu_ops *ops = cpu_get_ops(dev);
|
||||
static int reloc_done;
|
||||
|
||||
if (!reloc_done) {
|
||||
if (ops->get_desc)
|
||||
MANUAL_RELOC(ops->get_desc);
|
||||
if (ops->get_info)
|
||||
MANUAL_RELOC(ops->get_info);
|
||||
if (ops->get_count)
|
||||
MANUAL_RELOC(ops->get_count);
|
||||
if (ops->get_vendor)
|
||||
MANUAL_RELOC(ops->get_vendor);
|
||||
if (ops->is_current)
|
||||
MANUAL_RELOC(ops->is_current);
|
||||
|
||||
reloc_done++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(cpu) = {
|
||||
.id = UCLASS_CPU,
|
||||
.name = "cpu",
|
||||
.flags = DM_UC_FLAG_SEQ_ALIAS,
|
||||
.init = uclass_cpu_init,
|
||||
.post_bind = uclass_cpu_post_bind,
|
||||
};
|
||||
|
|
180
drivers/cpu/microblaze_cpu.c
Normal file
180
drivers/cpu/microblaze_cpu.c
Normal file
|
@ -0,0 +1,180 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2022, Ovidiu Panait <ovpanait@gmail.com>
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <cpu.h>
|
||||
#include <dm.h>
|
||||
#include <asm/cpuinfo.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/pvr.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define update_cpuinfo_pvr(pvr, ci, name) \
|
||||
{ \
|
||||
u32 tmp = PVR_##name(pvr); \
|
||||
if (ci != tmp) \
|
||||
printf("PVR value for " #name " does not match static data!\n");\
|
||||
ci = tmp; \
|
||||
}
|
||||
|
||||
static int microblaze_cpu_probe_all(void *ctx, struct event *event)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = cpu_probe_all();
|
||||
if (ret)
|
||||
return log_msg_ret("Microblaze cpus probe failed\n", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EVENT_SPY(EVT_DM_POST_INIT, microblaze_cpu_probe_all);
|
||||
|
||||
static void microblaze_set_cpuinfo_pvr(struct microblaze_cpuinfo *ci)
|
||||
{
|
||||
u32 pvr[PVR_FULL_COUNT];
|
||||
|
||||
microblaze_get_all_pvrs(pvr);
|
||||
|
||||
update_cpuinfo_pvr(pvr, ci->icache_size, ICACHE_BYTE_SIZE);
|
||||
update_cpuinfo_pvr(pvr, ci->icache_line_length, ICACHE_LINE_LEN);
|
||||
|
||||
update_cpuinfo_pvr(pvr, ci->dcache_size, DCACHE_BYTE_SIZE);
|
||||
update_cpuinfo_pvr(pvr, ci->dcache_line_length, DCACHE_LINE_LEN);
|
||||
|
||||
update_cpuinfo_pvr(pvr, ci->use_mmu, USE_MMU);
|
||||
update_cpuinfo_pvr(pvr, ci->ver_code, VERSION);
|
||||
update_cpuinfo_pvr(pvr, ci->fpga_code, TARGET_FAMILY);
|
||||
}
|
||||
|
||||
static void microblaze_set_cpuinfo_static(struct udevice *dev,
|
||||
struct microblaze_cpuinfo *ci)
|
||||
{
|
||||
const char *hw_ver = CONFIG_XILINX_MICROBLAZE0_HW_VER;
|
||||
const char *fpga_family = CONFIG_XILINX_MICROBLAZE0_FPGA_FAMILY;
|
||||
|
||||
ci->icache_size = dev_read_u32_default(dev, "i-cache-size", 0);
|
||||
ci->icache_line_length = dev_read_u32_default(dev,
|
||||
"i-cache-line-size", 0);
|
||||
|
||||
ci->dcache_size = dev_read_u32_default(dev, "d-cache-size", 0);
|
||||
ci->dcache_line_length = dev_read_u32_default(dev,
|
||||
"d-cache-line-size", 0);
|
||||
|
||||
ci->cpu_freq = dev_read_u32_default(dev, "clock-frequency", 0);
|
||||
ci->addr_size = dev_read_u32_default(dev, "xlnx,addr-size", 32);
|
||||
ci->use_mmu = dev_read_u32_default(dev, "xlnx,use-mmu", 0);
|
||||
|
||||
ci->ver_code = microblaze_lookup_cpu_version_code(hw_ver);
|
||||
ci->fpga_code = microblaze_lookup_fpga_family_code(fpga_family);
|
||||
}
|
||||
|
||||
static int microblaze_cpu_probe(struct udevice *dev)
|
||||
{
|
||||
microblaze_set_cpuinfo_static(dev, gd_cpuinfo());
|
||||
|
||||
if (microblaze_cpu_has_pvr_full())
|
||||
microblaze_set_cpuinfo_pvr(gd_cpuinfo());
|
||||
else
|
||||
debug("No PVR support. Using only static CPU info.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int microblaze_cpu_get_desc(const struct udevice *dev, char *buf,
|
||||
int size)
|
||||
{
|
||||
struct microblaze_cpuinfo *ci = gd_cpuinfo();
|
||||
const char *cpu_ver, *fpga_family;
|
||||
u32 cpu_freq_mhz;
|
||||
int ret;
|
||||
|
||||
cpu_freq_mhz = ci->cpu_freq / 1000000;
|
||||
cpu_ver = microblaze_lookup_cpu_version_string(ci->ver_code);
|
||||
fpga_family = microblaze_lookup_fpga_family_string(ci->fpga_code);
|
||||
|
||||
ret = snprintf(buf, size,
|
||||
"MicroBlaze @ %uMHz, Rev: %s, FPGA family: %s",
|
||||
cpu_freq_mhz, cpu_ver, fpga_family);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int microblaze_cpu_get_info(const struct udevice *dev,
|
||||
struct cpu_info *info)
|
||||
{
|
||||
struct microblaze_cpuinfo *ci = gd_cpuinfo();
|
||||
|
||||
info->cpu_freq = ci->cpu_freq;
|
||||
info->address_width = ci->addr_size;
|
||||
|
||||
if (ci->icache_size || ci->dcache_size)
|
||||
info->features |= BIT(CPU_FEAT_L1_CACHE);
|
||||
|
||||
if (ci->use_mmu)
|
||||
info->features |= BIT(CPU_FEAT_MMU);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int microblaze_cpu_get_count(const struct udevice *dev)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct cpu_ops microblaze_cpu_ops = {
|
||||
.get_desc = microblaze_cpu_get_desc,
|
||||
.get_info = microblaze_cpu_get_info,
|
||||
.get_count = microblaze_cpu_get_count,
|
||||
};
|
||||
|
||||
static const struct udevice_id microblaze_cpu_ids[] = {
|
||||
{ .compatible = "xlnx,microblaze-11.0" },
|
||||
{ .compatible = "xlnx,microblaze-10.0" },
|
||||
{ .compatible = "xlnx,microblaze-9.6" },
|
||||
{ .compatible = "xlnx,microblaze-9.5" },
|
||||
{ .compatible = "xlnx,microblaze-9.4" },
|
||||
{ .compatible = "xlnx,microblaze-9.3" },
|
||||
{ .compatible = "xlnx,microblaze-9.2" },
|
||||
{ .compatible = "xlnx,microblaze-9.1" },
|
||||
{ .compatible = "xlnx,microblaze-9.0" },
|
||||
{ .compatible = "xlnx,microblaze-8.50.c" },
|
||||
{ .compatible = "xlnx,microblaze-8.50.b" },
|
||||
{ .compatible = "xlnx,microblaze-8.50.a" },
|
||||
{ .compatible = "xlnx,microblaze-8.40.b" },
|
||||
{ .compatible = "xlnx,microblaze-8.40.a" },
|
||||
{ .compatible = "xlnx,microblaze-8.30.a" },
|
||||
{ .compatible = "xlnx,microblaze-8.20.b" },
|
||||
{ .compatible = "xlnx,microblaze-8.20.a" },
|
||||
{ .compatible = "xlnx,microblaze-8.10.a" },
|
||||
{ .compatible = "xlnx,microblaze-8.00.b" },
|
||||
{ .compatible = "xlnx,microblaze-8.00.a" },
|
||||
{ .compatible = "xlnx,microblaze-7.30.b" },
|
||||
{ .compatible = "xlnx,microblaze-7.30.a" },
|
||||
{ .compatible = "xlnx,microblaze-7.20.d" },
|
||||
{ .compatible = "xlnx,microblaze-7.20.c" },
|
||||
{ .compatible = "xlnx,microblaze-7.20.b" },
|
||||
{ .compatible = "xlnx,microblaze-7.20.a" },
|
||||
{ .compatible = "xlnx,microblaze-7.10.d" },
|
||||
{ .compatible = "xlnx,microblaze-7.10.c" },
|
||||
{ .compatible = "xlnx,microblaze-7.10.b" },
|
||||
{ .compatible = "xlnx,microblaze-7.10.a" },
|
||||
{ .compatible = "xlnx,microblaze-7.00.b" },
|
||||
{ .compatible = "xlnx,microblaze-7.00.a" },
|
||||
{ .compatible = "xlnx,microblaze-6.00.b" },
|
||||
{ .compatible = "xlnx,microblaze-6.00.a" },
|
||||
{ .compatible = "xlnx,microblaze-5.00.c" },
|
||||
{ .compatible = "xlnx,microblaze-5.00.b" },
|
||||
{ .compatible = "xlnx,microblaze-5.00.a" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(microblaze_cpu) = {
|
||||
.name = "microblaze_cpu",
|
||||
.id = UCLASS_CPU,
|
||||
.of_match = microblaze_cpu_ids,
|
||||
.probe = microblaze_cpu_probe,
|
||||
.ops = µblaze_cpu_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
|
@ -26,7 +26,7 @@
|
|||
struct zynqmp_power {
|
||||
struct mbox_chan tx_chan;
|
||||
struct mbox_chan rx_chan;
|
||||
} zynqmp_power;
|
||||
} zynqmp_power = {};
|
||||
|
||||
#define NODE_ID_LOCATION 5
|
||||
|
||||
|
@ -79,6 +79,20 @@ int zynqmp_pmufw_node(u32 id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int do_pm_probe(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_FIRMWARE,
|
||||
DM_DRIVER_GET(zynqmp_power),
|
||||
&dev);
|
||||
if (ret)
|
||||
debug("%s: Probing device failed: %d\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ipi_req(const u32 *req, size_t req_len, u32 *res, size_t res_maxlen)
|
||||
{
|
||||
struct zynqmp_ipi_msg msg;
|
||||
|
@ -92,8 +106,11 @@ static int ipi_req(const u32 *req, size_t req_len, u32 *res, size_t res_maxlen)
|
|||
res_maxlen > PMUFW_PAYLOAD_ARG_CNT)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(zynqmp_power.tx_chan.dev) || !(&zynqmp_power.rx_chan.dev))
|
||||
return -EINVAL;
|
||||
if (!(zynqmp_power.tx_chan.dev) || !(zynqmp_power.rx_chan.dev)) {
|
||||
ret = do_pm_probe();
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
debug("%s, Sending IPI message with ID: 0x%0x\n", __func__, req[0]);
|
||||
msg.buf = (u32 *)req;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <miiphy.h>
|
||||
#include <wait_bit.h>
|
||||
#include <linux/delay.h>
|
||||
#include <eth_phy.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -295,6 +296,9 @@ static int axiemac_phy_init(struct udevice *dev)
|
|||
/* Set default MDIO divisor */
|
||||
writel(XAE_MDIO_DIV_DFT | XAE_MDIO_MC_MDIOEN_MASK, ®s->mdio_mc);
|
||||
|
||||
if (IS_ENABLED(CONFIG_DM_ETH_PHY))
|
||||
priv->phyaddr = eth_phy_get_addr(dev);
|
||||
|
||||
if (priv->phyaddr == -1) {
|
||||
/* Detect the PHY address */
|
||||
for (i = 31; i >= 0; i--) {
|
||||
|
@ -778,18 +782,29 @@ static int axi_emac_probe(struct udevice *dev)
|
|||
priv->phy_of_handle = plat->phy_of_handle;
|
||||
priv->interface = pdata->phy_interface;
|
||||
|
||||
priv->bus = mdio_alloc();
|
||||
priv->bus->read = axiemac_miiphy_read;
|
||||
priv->bus->write = axiemac_miiphy_write;
|
||||
priv->bus->priv = priv;
|
||||
if (IS_ENABLED(CONFIG_DM_ETH_PHY))
|
||||
priv->bus = eth_phy_get_mdio_bus(dev);
|
||||
|
||||
ret = mdio_register_seq(priv->bus, dev_seq(dev));
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!priv->bus) {
|
||||
priv->bus = mdio_alloc();
|
||||
priv->bus->read = axiemac_miiphy_read;
|
||||
priv->bus->write = axiemac_miiphy_write;
|
||||
priv->bus->priv = priv;
|
||||
|
||||
ret = mdio_register_seq(priv->bus, dev_seq(dev));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_DM_ETH_PHY))
|
||||
eth_phy_set_mdio_bus(dev, priv->bus);
|
||||
|
||||
axiemac_phy_init(dev);
|
||||
}
|
||||
|
||||
printf("AXI EMAC: %lx, phyaddr %d, interface %s\n", (ulong)pdata->iobase,
|
||||
priv->phyaddr, phy_string_for_interface(pdata->phy_interface));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -844,8 +859,10 @@ static int axi_emac_of_to_plat(struct udevice *dev)
|
|||
offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
|
||||
"phy-handle");
|
||||
if (offset > 0) {
|
||||
plat->phyaddr = fdtdec_get_int(gd->fdt_blob, offset,
|
||||
"reg", -1);
|
||||
if (!(IS_ENABLED(CONFIG_DM_ETH_PHY)))
|
||||
plat->phyaddr = fdtdec_get_int(gd->fdt_blob,
|
||||
offset,
|
||||
"reg", -1);
|
||||
plat->phy_of_handle = offset;
|
||||
}
|
||||
|
||||
|
@ -857,9 +874,6 @@ static int axi_emac_of_to_plat(struct udevice *dev)
|
|||
"xlnx,eth-hasnobuf");
|
||||
}
|
||||
|
||||
printf("AXI EMAC: %lx, phyaddr %d, interface %s\n", (ulong)pdata->iobase,
|
||||
plat->phyaddr, phy_string_for_interface(pdata->phy_interface));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/io.h>
|
||||
#include <eth_phy.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -564,14 +565,27 @@ static int emaclite_probe(struct udevice *dev)
|
|||
struct xemaclite *emaclite = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
emaclite->bus = mdio_alloc();
|
||||
emaclite->bus->read = emaclite_miiphy_read;
|
||||
emaclite->bus->write = emaclite_miiphy_write;
|
||||
emaclite->bus->priv = emaclite;
|
||||
if (IS_ENABLED(CONFIG_DM_ETH_PHY))
|
||||
emaclite->bus = eth_phy_get_mdio_bus(dev);
|
||||
|
||||
ret = mdio_register_seq(emaclite->bus, dev_seq(dev));
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!emaclite->bus) {
|
||||
emaclite->bus = mdio_alloc();
|
||||
emaclite->bus->read = emaclite_miiphy_read;
|
||||
emaclite->bus->write = emaclite_miiphy_write;
|
||||
emaclite->bus->priv = emaclite;
|
||||
|
||||
ret = mdio_register_seq(emaclite->bus, dev_seq(dev));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_DM_ETH_PHY)) {
|
||||
eth_phy_set_mdio_bus(dev, emaclite->bus);
|
||||
emaclite->phyaddr = eth_phy_get_addr(dev);
|
||||
}
|
||||
|
||||
printf("EMACLITE: %lx, phyaddr %d, %d/%d\n", (ulong)emaclite->regs,
|
||||
emaclite->phyaddr, emaclite->txpp, emaclite->rxpp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -606,20 +620,19 @@ static int emaclite_of_to_plat(struct udevice *dev)
|
|||
|
||||
emaclite->phyaddr = -1;
|
||||
|
||||
offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev),
|
||||
"phy-handle");
|
||||
if (offset > 0)
|
||||
emaclite->phyaddr = fdtdec_get_int(gd->fdt_blob, offset,
|
||||
"reg", -1);
|
||||
if (!(IS_ENABLED(CONFIG_DM_ETH_PHY))) {
|
||||
offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev),
|
||||
"phy-handle");
|
||||
if (offset > 0)
|
||||
emaclite->phyaddr = fdtdec_get_int(gd->fdt_blob,
|
||||
offset, "reg", -1);
|
||||
}
|
||||
|
||||
emaclite->txpp = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
|
||||
"xlnx,tx-ping-pong", 0);
|
||||
emaclite->rxpp = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
|
||||
"xlnx,rx-ping-pong", 0);
|
||||
|
||||
printf("EMACLITE: %lx, phyaddr %d, %d/%d\n", (ulong)emaclite->regs,
|
||||
emaclite->phyaddr, emaclite->txpp, emaclite->rxpp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -467,6 +467,10 @@ static int zynqmp_pinconf_set(struct udevice *dev, unsigned int pin,
|
|||
pin);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
param = PM_PINCTRL_CONFIG_TRI_STATE;
|
||||
arg = PM_PINCTRL_TRI_STATE_ENABLE;
|
||||
ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
|
||||
break;
|
||||
case PIN_CONFIG_LOW_POWER_MODE:
|
||||
/*
|
||||
* This cases are mentioned in dts but configurable
|
||||
|
@ -475,6 +479,11 @@ static int zynqmp_pinconf_set(struct udevice *dev, unsigned int pin,
|
|||
*/
|
||||
ret = 0;
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
param = PM_PINCTRL_CONFIG_TRI_STATE;
|
||||
arg = PM_PINCTRL_TRI_STATE_DISABLE;
|
||||
ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
|
||||
break;
|
||||
default:
|
||||
dev_warn(dev, "unsupported configuration parameter '%u'\n",
|
||||
param);
|
||||
|
|
|
@ -476,6 +476,8 @@ config DEBUG_UART_BASE
|
|||
depends on DEBUG_UART
|
||||
default 0 if DEBUG_SBI_CONSOLE
|
||||
default 0 if DEBUG_UART_SANDBOX
|
||||
default 0xff000000 if DEBUG_UART_ZYNQ && ARCH_ZYNQMP
|
||||
default 0xe0000000 if DEBUG_UART_ZYNQ && ARCH_ZYNQ
|
||||
help
|
||||
This is the base address of your UART for memory-mapped UARTs.
|
||||
|
||||
|
@ -502,6 +504,8 @@ config DEBUG_UART_CLOCK
|
|||
default 0 if DEBUG_SBI_CONSOLE
|
||||
default 0 if DEBUG_UART_SANDBOX
|
||||
default 0 if DEBUG_MVEBU_A3700_UART
|
||||
default 100000000 if DEBUG_UART_ZYNQ && ARCH_ZYNQMP
|
||||
default 50000000 if DEBUG_UART_ZYNQ && ARCH_ZYNQ
|
||||
help
|
||||
The UART input clock determines the speed of the internal UART
|
||||
circuitry. The baud rate is derived from this by dividing the input
|
||||
|
|
|
@ -3,10 +3,15 @@
|
|||
* Xilinx ZynqMP SOC driver
|
||||
*
|
||||
* Copyright (C) 2021 Xilinx, Inc.
|
||||
* Michal Simek <michal.simek@xilinx.com>
|
||||
*
|
||||
* Copyright (C) 2022 Weidmüller Interface GmbH & Co. KG
|
||||
* Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <asm/cache.h>
|
||||
#include <soc.h>
|
||||
#include <zynqmp_firmware.h>
|
||||
|
@ -22,11 +27,257 @@
|
|||
*/
|
||||
static const char zynqmp_family[] = "ZynqMP";
|
||||
|
||||
#define EFUSE_VCU_DIS_SHIFT 8
|
||||
#define EFUSE_VCU_DIS_MASK BIT(EFUSE_VCU_DIS_SHIFT)
|
||||
#define EFUSE_GPU_DIS_SHIFT 5
|
||||
#define EFUSE_GPU_DIS_MASK BIT(EFUSE_GPU_DIS_SHIFT)
|
||||
#define IDCODE_DEV_TYPE_MASK GENMASK(27, 0)
|
||||
#define IDCODE2_PL_INIT_SHIFT 9
|
||||
#define IDCODE2_PL_INIT_MASK BIT(IDCODE2_PL_INIT_SHIFT)
|
||||
|
||||
#define ZYNQMP_VERSION_SIZE 7
|
||||
|
||||
enum {
|
||||
ZYNQMP_VARIANT_EG = BIT(0),
|
||||
ZYNQMP_VARIANT_EV = BIT(1),
|
||||
ZYNQMP_VARIANT_CG = BIT(2),
|
||||
ZYNQMP_VARIANT_DR = BIT(3),
|
||||
};
|
||||
|
||||
struct zynqmp_device {
|
||||
u32 id;
|
||||
u8 device;
|
||||
u8 variants;
|
||||
};
|
||||
|
||||
struct soc_xilinx_zynqmp_priv {
|
||||
const char *family;
|
||||
char machine[ZYNQMP_VERSION_SIZE];
|
||||
char revision;
|
||||
};
|
||||
|
||||
static const struct zynqmp_device zynqmp_devices[] = {
|
||||
{
|
||||
.id = 0x04688093,
|
||||
.device = 1,
|
||||
.variants = ZYNQMP_VARIANT_EG,
|
||||
},
|
||||
{
|
||||
.id = 0x04711093,
|
||||
.device = 2,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
|
||||
},
|
||||
{
|
||||
.id = 0x04710093,
|
||||
.device = 3,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
|
||||
},
|
||||
{
|
||||
.id = 0x04721093,
|
||||
.device = 4,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG |
|
||||
ZYNQMP_VARIANT_EV,
|
||||
},
|
||||
{
|
||||
.id = 0x04720093,
|
||||
.device = 5,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG |
|
||||
ZYNQMP_VARIANT_EV,
|
||||
},
|
||||
{
|
||||
.id = 0x04739093,
|
||||
.device = 6,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
|
||||
},
|
||||
{
|
||||
.id = 0x04730093,
|
||||
.device = 7,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG |
|
||||
ZYNQMP_VARIANT_EV,
|
||||
},
|
||||
{
|
||||
.id = 0x04738093,
|
||||
.device = 9,
|
||||
.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
|
||||
},
|
||||
{
|
||||
.id = 0x04740093,
|
||||
.device = 11,
|
||||
.variants = ZYNQMP_VARIANT_EG,
|
||||
},
|
||||
{
|
||||
.id = 0x04750093,
|
||||
.device = 15,
|
||||
.variants = ZYNQMP_VARIANT_EG,
|
||||
},
|
||||
{
|
||||
.id = 0x04759093,
|
||||
.device = 17,
|
||||
.variants = ZYNQMP_VARIANT_EG,
|
||||
},
|
||||
{
|
||||
.id = 0x04758093,
|
||||
.device = 19,
|
||||
.variants = ZYNQMP_VARIANT_EG,
|
||||
},
|
||||
{
|
||||
.id = 0x047E1093,
|
||||
.device = 21,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047E3093,
|
||||
.device = 23,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047E5093,
|
||||
.device = 25,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047E4093,
|
||||
.device = 27,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047E0093,
|
||||
.device = 28,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047E2093,
|
||||
.device = 29,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047E6093,
|
||||
.device = 39,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047FD093,
|
||||
.device = 43,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047F8093,
|
||||
.device = 46,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047FF093,
|
||||
.device = 47,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047FB093,
|
||||
.device = 48,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x047FE093,
|
||||
.device = 49,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x046d0093,
|
||||
.device = 67,
|
||||
.variants = ZYNQMP_VARIANT_DR,
|
||||
},
|
||||
{
|
||||
.id = 0x04714093,
|
||||
.device = 24,
|
||||
.variants = 0,
|
||||
},
|
||||
{
|
||||
.id = 0x04724093,
|
||||
.device = 26,
|
||||
.variants = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct zynqmp_device *zynqmp_get_device(u32 idcode)
|
||||
{
|
||||
idcode &= IDCODE_DEV_TYPE_MASK;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
|
||||
if (zynqmp_devices[i].id == idcode)
|
||||
return &zynqmp_devices[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int soc_xilinx_zynqmp_detect_machine(struct udevice *dev, u32 idcode,
|
||||
u32 idcode2)
|
||||
{
|
||||
struct soc_xilinx_zynqmp_priv *priv = dev_get_priv(dev);
|
||||
const struct zynqmp_device *device;
|
||||
int ret;
|
||||
|
||||
device = zynqmp_get_device(idcode);
|
||||
if (!device)
|
||||
return 0;
|
||||
|
||||
/* Add device prefix to the name */
|
||||
ret = snprintf(priv->machine, sizeof(priv->machine), "%s%d",
|
||||
device->variants ? "zu" : "xck", device->device);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (device->variants & ZYNQMP_VARIANT_EV) {
|
||||
/* Devices with EV variant might be EG/CG/EV family */
|
||||
if (idcode2 & IDCODE2_PL_INIT_MASK) {
|
||||
u32 family = ((idcode2 & EFUSE_VCU_DIS_MASK) >>
|
||||
EFUSE_VCU_DIS_SHIFT) << 1 |
|
||||
((idcode2 & EFUSE_GPU_DIS_MASK) >>
|
||||
EFUSE_GPU_DIS_SHIFT);
|
||||
|
||||
/*
|
||||
* Get family name based on extended idcode values as
|
||||
* determined on UG1087, EXTENDED_IDCODE register
|
||||
* description
|
||||
*/
|
||||
switch (family) {
|
||||
case 0x00:
|
||||
strlcat(priv->machine, "ev",
|
||||
sizeof(priv->machine));
|
||||
break;
|
||||
case 0x10:
|
||||
strlcat(priv->machine, "eg",
|
||||
sizeof(priv->machine));
|
||||
break;
|
||||
case 0x11:
|
||||
strlcat(priv->machine, "cg",
|
||||
sizeof(priv->machine));
|
||||
break;
|
||||
default:
|
||||
/* Do not append family name*/
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* When PL powered down the VCU Disable efuse cannot be
|
||||
* read. So, ignore the bit and just findout if it is CG
|
||||
* or EG/EV variant.
|
||||
*/
|
||||
strlcat(priv->machine, (idcode2 & EFUSE_GPU_DIS_MASK) ?
|
||||
"cg" : "e", sizeof(priv->machine));
|
||||
}
|
||||
} else if (device->variants & ZYNQMP_VARIANT_CG) {
|
||||
/* Devices with CG variant might be EG or CG family */
|
||||
strlcat(priv->machine, (idcode2 & EFUSE_GPU_DIS_MASK) ?
|
||||
"cg" : "eg", sizeof(priv->machine));
|
||||
} else if (device->variants & ZYNQMP_VARIANT_EG) {
|
||||
strlcat(priv->machine, "eg", sizeof(priv->machine));
|
||||
} else if (device->variants & ZYNQMP_VARIANT_DR) {
|
||||
strlcat(priv->machine, "dr", sizeof(priv->machine));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int soc_xilinx_zynqmp_get_family(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
struct soc_xilinx_zynqmp_priv *priv = dev_get_priv(dev);
|
||||
|
@ -34,6 +285,17 @@ static int soc_xilinx_zynqmp_get_family(struct udevice *dev, char *buf, int size
|
|||
return snprintf(buf, size, "%s", priv->family);
|
||||
}
|
||||
|
||||
int soc_xilinx_zynqmp_get_machine(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
struct soc_xilinx_zynqmp_priv *priv = dev_get_priv(dev);
|
||||
const char *machine = priv->machine;
|
||||
|
||||
if (!machine[0])
|
||||
machine = "unknown";
|
||||
|
||||
return snprintf(buf, size, "%s", machine);
|
||||
}
|
||||
|
||||
static int soc_xilinx_zynqmp_get_revision(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
struct soc_xilinx_zynqmp_priv *priv = dev_get_priv(dev);
|
||||
|
@ -44,6 +306,7 @@ static int soc_xilinx_zynqmp_get_revision(struct udevice *dev, char *buf, int si
|
|||
static const struct soc_ops soc_xilinx_zynqmp_ops = {
|
||||
.get_family = soc_xilinx_zynqmp_get_family,
|
||||
.get_revision = soc_xilinx_zynqmp_get_revision,
|
||||
.get_machine = soc_xilinx_zynqmp_get_machine,
|
||||
};
|
||||
|
||||
static int soc_xilinx_zynqmp_probe(struct udevice *dev)
|
||||
|
@ -54,8 +317,7 @@ static int soc_xilinx_zynqmp_probe(struct udevice *dev)
|
|||
|
||||
priv->family = zynqmp_family;
|
||||
|
||||
if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3 ||
|
||||
!IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE))
|
||||
if (!IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE))
|
||||
ret = zynqmp_mmio_read(ZYNQMP_PS_VERSION, &ret_payload[2]);
|
||||
else
|
||||
ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0,
|
||||
|
@ -65,6 +327,26 @@ static int soc_xilinx_zynqmp_probe(struct udevice *dev)
|
|||
|
||||
priv->revision = ret_payload[2] & ZYNQMP_PS_VER_MASK;
|
||||
|
||||
if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE)) {
|
||||
/*
|
||||
* Firmware returns:
|
||||
* payload[0][31:0] = status of the operation
|
||||
* payload[1] = IDCODE
|
||||
* payload[2][19:0] = Version
|
||||
* payload[2][28:20] = EXTENDED_IDCODE
|
||||
* payload[2][29] = PL_INIT
|
||||
*/
|
||||
u32 idcode = ret_payload[1];
|
||||
u32 idcode2 = ret_payload[2] >>
|
||||
ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
|
||||
dev_dbg(dev, "IDCODE: 0x%0x, IDCODE2: 0x%0x\n", idcode,
|
||||
idcode2);
|
||||
|
||||
ret = soc_xilinx_zynqmp_detect_machine(dev, idcode, idcode2);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -279,4 +279,13 @@ config IMX_GPT_TIMER
|
|||
Select this to enable support for the timer found on
|
||||
NXP i.MX devices.
|
||||
|
||||
config XILINX_TIMER
|
||||
bool "Xilinx timer support"
|
||||
depends on TIMER
|
||||
select REGMAP
|
||||
select SPL_REGMAP if SPL
|
||||
help
|
||||
Select this to enable support for the timer found on
|
||||
any Xilinx boards (axi timer).
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -28,3 +28,4 @@ obj-$(CONFIG_X86_TSC_TIMER) += tsc_timer.o
|
|||
obj-$(CONFIG_MTK_TIMER) += mtk_timer.o
|
||||
obj-$(CONFIG_MCHP_PIT64B_TIMER) += mchp-pit64b-timer.o
|
||||
obj-$(CONFIG_IMX_GPT_TIMER) += imx-gpt-timer.o
|
||||
obj-$(CONFIG_XILINX_TIMER) += xilinx-timer.o
|
||||
|
|
82
drivers/timer/xilinx-timer.c
Normal file
82
drivers/timer/xilinx-timer.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2022 Advanced Micro Devices, Inc
|
||||
* Michal Simek <michal.simek@amd.com>
|
||||
*
|
||||
* (C) Copyright 2007 Michal Simek
|
||||
* Michal SIMEK <monstr@monstr.eu>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <timer.h>
|
||||
#include <regmap.h>
|
||||
#include <dm/device_compat.h>
|
||||
|
||||
#define TIMER_ENABLE_ALL 0x400 /* ENALL */
|
||||
#define TIMER_PWM 0x200 /* PWMA0 */
|
||||
#define TIMER_INTERRUPT 0x100 /* T0INT */
|
||||
#define TIMER_ENABLE 0x080 /* ENT0 */
|
||||
#define TIMER_ENABLE_INTR 0x040 /* ENIT0 */
|
||||
#define TIMER_RESET 0x020 /* LOAD0 */
|
||||
#define TIMER_RELOAD 0x010 /* ARHT0 */
|
||||
#define TIMER_EXT_CAPTURE 0x008 /* CAPT0 */
|
||||
#define TIMER_EXT_COMPARE 0x004 /* GENT0 */
|
||||
#define TIMER_DOWN_COUNT 0x002 /* UDT0 */
|
||||
#define TIMER_CAPTURE_MODE 0x001 /* MDT0 */
|
||||
|
||||
#define TIMER_CONTROL_OFFSET 0
|
||||
#define TIMER_LOADREG_OFFSET 4
|
||||
#define TIMER_COUNTER_OFFSET 8
|
||||
|
||||
struct xilinx_timer_priv {
|
||||
struct regmap *regs;
|
||||
};
|
||||
|
||||
static u64 xilinx_timer_get_count(struct udevice *dev)
|
||||
{
|
||||
struct xilinx_timer_priv *priv = dev_get_priv(dev);
|
||||
u32 value;
|
||||
|
||||
regmap_read(priv->regs, TIMER_COUNTER_OFFSET, &value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static int xilinx_timer_probe(struct udevice *dev)
|
||||
{
|
||||
struct xilinx_timer_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
/* uc_priv->clock_rate has already clock rate */
|
||||
ret = regmap_init_mem(dev_ofnode(dev), &priv->regs);
|
||||
if (ret) {
|
||||
dev_dbg(dev, "failed to get regbase of timer\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
regmap_write(priv->regs, TIMER_LOADREG_OFFSET, 0);
|
||||
regmap_write(priv->regs, TIMER_CONTROL_OFFSET, TIMER_RESET);
|
||||
regmap_write(priv->regs, TIMER_CONTROL_OFFSET,
|
||||
TIMER_ENABLE | TIMER_RELOAD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct timer_ops xilinx_timer_ops = {
|
||||
.get_count = xilinx_timer_get_count,
|
||||
};
|
||||
|
||||
static const struct udevice_id xilinx_timer_ids[] = {
|
||||
{ .compatible = "xlnx,xps-timer-1.00.a" },
|
||||
{}
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(xilinx_timer) = {
|
||||
.name = "xilinx_timer",
|
||||
.id = UCLASS_TIMER,
|
||||
.of_match = xilinx_timer_ids,
|
||||
.priv_auto = sizeof(struct xilinx_timer_priv),
|
||||
.probe = xilinx_timer_probe,
|
||||
.ops = &xilinx_timer_ops,
|
||||
};
|
|
@ -18,10 +18,6 @@
|
|||
# define CONFIG_SYS_BAUDRATE_TABLE \
|
||||
{300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}
|
||||
|
||||
/* Stack location before relocation */
|
||||
#define CONFIG_SYS_INIT_SP_OFFSET (CONFIG_SYS_TEXT_BASE - \
|
||||
CONFIG_SYS_MALLOC_F_LEN)
|
||||
|
||||
#ifdef CONFIG_CFI_FLASH
|
||||
/* ?empty sector */
|
||||
# define CONFIG_SYS_FLASH_EMPTY_INFO 1
|
||||
|
@ -30,10 +26,6 @@
|
|||
# define CONFIG_SYS_MAX_FLASH_SECT 2048
|
||||
#endif
|
||||
|
||||
#ifndef XILINX_DCACHE_BYTE_SIZE
|
||||
#define XILINX_DCACHE_BYTE_SIZE 32768
|
||||
#endif
|
||||
|
||||
#define CONFIG_HOSTNAME "microblaze-generic"
|
||||
|
||||
/* architecture dependent code */
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
#define R_AARCH64_RELATIVE 1027
|
||||
#endif
|
||||
|
||||
static int ei_class;
|
||||
|
||||
static uint64_t rela_start, rela_end, text_base, dyn_start;
|
||||
|
||||
static const bool debug_en;
|
||||
|
||||
static void debug(const char *fmt, ...)
|
||||
|
@ -52,58 +56,310 @@ static bool supported_rela(Elf64_Rela *rela)
|
|||
}
|
||||
}
|
||||
|
||||
static bool read_num(const char *str, uint64_t *num)
|
||||
static int decode_elf64(FILE *felf, char **argv)
|
||||
{
|
||||
char *endptr;
|
||||
*num = strtoull(str, &endptr, 16);
|
||||
return str[0] && !endptr[0];
|
||||
}
|
||||
size_t size;
|
||||
Elf64_Ehdr header;
|
||||
uint64_t section_header_base, section_header_size, sh_offset, sh_size;
|
||||
Elf64_Shdr *sh_table; /* Elf symbol table */
|
||||
int ret, i, machine;
|
||||
char *sh_str;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *f;
|
||||
int i, num;
|
||||
uint64_t rela_start, rela_end, text_base, file_size;
|
||||
debug("64bit version\n");
|
||||
|
||||
if (argc != 5) {
|
||||
fprintf(stderr, "Statically apply ELF rela relocations\n");
|
||||
fprintf(stderr, "Usage: %s <bin file> <text base> " \
|
||||
"<rela start> <rela end>\n", argv[0]);
|
||||
fprintf(stderr, "All numbers in hex.\n");
|
||||
return 1;
|
||||
/* Make sure we are at start */
|
||||
rewind(felf);
|
||||
|
||||
size = fread(&header, 1, sizeof(header), felf);
|
||||
if (size != sizeof(header)) {
|
||||
fclose(felf);
|
||||
return 25;
|
||||
}
|
||||
|
||||
f = fopen(argv[1], "r+b");
|
||||
if (!f) {
|
||||
machine = header.e_machine;
|
||||
debug("Machine\t%d\n", machine);
|
||||
|
||||
if (machine != EM_AARCH64) {
|
||||
fprintf(stderr, "%s: Not supported machine type\n", argv[0]);
|
||||
return 30;
|
||||
}
|
||||
|
||||
text_base = header.e_entry;
|
||||
section_header_base = header.e_shoff;
|
||||
section_header_size = header.e_shentsize * header.e_shnum;
|
||||
|
||||
sh_table = malloc(section_header_size);
|
||||
if (!sh_table) {
|
||||
fprintf(stderr, "%s: Cannot allocate space for section header\n",
|
||||
argv[0]);
|
||||
fclose(felf);
|
||||
return 26;
|
||||
}
|
||||
|
||||
ret = fseek(felf, section_header_base, SEEK_SET);
|
||||
if (ret) {
|
||||
fprintf(stderr, "%s: Can't set pointer to section header: %x/%lx\n",
|
||||
argv[0], ret, section_header_base);
|
||||
free(sh_table);
|
||||
fclose(felf);
|
||||
return 26;
|
||||
}
|
||||
|
||||
size = fread(sh_table, 1, section_header_size, felf);
|
||||
if (size != section_header_size) {
|
||||
fprintf(stderr, "%s: Can't read section header: %lx/%lx\n",
|
||||
argv[0], size, section_header_size);
|
||||
free(sh_table);
|
||||
fclose(felf);
|
||||
return 27;
|
||||
}
|
||||
|
||||
sh_size = sh_table[header.e_shstrndx].sh_size;
|
||||
debug("e_shstrndx\t0x%08x\n", header.e_shstrndx);
|
||||
debug("sh_size\t\t0x%08lx\n", sh_size);
|
||||
|
||||
sh_str = malloc(sh_size);
|
||||
if (!sh_str) {
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
free(sh_table);
|
||||
fclose(felf);
|
||||
return 28;
|
||||
}
|
||||
|
||||
/*
|
||||
* Specifies the byte offset from the beginning of the file
|
||||
* to the first byte in the section.
|
||||
*/
|
||||
sh_offset = sh_table[header.e_shstrndx].sh_offset;
|
||||
|
||||
debug("sh_offset\t0x%08x\n", header.e_shnum);
|
||||
|
||||
ret = fseek(felf, sh_offset, SEEK_SET);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Setting up sh_offset failed\n");
|
||||
free(sh_str);
|
||||
free(sh_table);
|
||||
fclose(felf);
|
||||
return 29;
|
||||
}
|
||||
|
||||
size = fread(sh_str, 1, sh_size, felf);
|
||||
if (size != sh_size) {
|
||||
fprintf(stderr, "%s: Can't read section: %lx/%lx\n",
|
||||
argv[0], size, sh_size);
|
||||
free(sh_str);
|
||||
free(sh_table);
|
||||
fclose(felf);
|
||||
return 30;
|
||||
}
|
||||
|
||||
for (i = 0; i < header.e_shnum; i++) {
|
||||
/* fprintf(stderr, "%s\n", sh_str + sh_table[i].sh_name); Debug only */
|
||||
if (!strcmp(".rela.dyn", (sh_str + sh_table[i].sh_name))) {
|
||||
debug("Found section\t\".rela_dyn\"\n");
|
||||
debug(" at addr\t0x%08x\n",
|
||||
(unsigned int)sh_table[i].sh_addr);
|
||||
debug(" at offset\t0x%08x\n",
|
||||
(unsigned int)sh_table[i].sh_offset);
|
||||
debug(" of size\t0x%08x\n",
|
||||
(unsigned int)sh_table[i].sh_size);
|
||||
rela_start = sh_table[i].sh_addr;
|
||||
rela_end = rela_start + sh_table[i].sh_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
free(sh_str);
|
||||
free(sh_table);
|
||||
fclose(felf);
|
||||
|
||||
debug("text_base\t0x%08lx\n", text_base);
|
||||
debug("rela_start\t0x%08lx\n", rela_start);
|
||||
debug("rela_end\t0x%08lx\n", rela_end);
|
||||
|
||||
if (!rela_start)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_elf32(FILE *felf, char **argv)
|
||||
{
|
||||
size_t size;
|
||||
Elf32_Ehdr header;
|
||||
uint64_t section_header_base, section_header_size, sh_offset, sh_size;
|
||||
Elf32_Shdr *sh_table; /* Elf symbol table */
|
||||
int ret, i, machine;
|
||||
char *sh_str;
|
||||
|
||||
debug("32bit version\n");
|
||||
|
||||
/* Make sure we are at start */
|
||||
rewind(felf);
|
||||
|
||||
size = fread(&header, 1, sizeof(header), felf);
|
||||
if (size != sizeof(header)) {
|
||||
fclose(felf);
|
||||
return 25;
|
||||
}
|
||||
|
||||
machine = header.e_machine;
|
||||
debug("Machine %d\n", machine);
|
||||
|
||||
if (machine != EM_MICROBLAZE) {
|
||||
fprintf(stderr, "%s: Not supported machine type\n", argv[0]);
|
||||
return 30;
|
||||
}
|
||||
|
||||
text_base = header.e_entry;
|
||||
section_header_base = header.e_shoff;
|
||||
|
||||
debug("Section header base %x\n", section_header_base);
|
||||
|
||||
section_header_size = header.e_shentsize * header.e_shnum;
|
||||
|
||||
debug("Section header size %d\n", section_header_size);
|
||||
|
||||
sh_table = malloc(section_header_size);
|
||||
if (!sh_table) {
|
||||
fprintf(stderr, "%s: Cannot allocate space for section header\n",
|
||||
argv[0]);
|
||||
fclose(felf);
|
||||
return 26;
|
||||
}
|
||||
|
||||
ret = fseek(felf, section_header_base, SEEK_SET);
|
||||
if (ret) {
|
||||
fprintf(stderr, "%s: Can't set pointer to section header: %x/%lx\n",
|
||||
argv[0], ret, section_header_base);
|
||||
free(sh_table);
|
||||
fclose(felf);
|
||||
return 26;
|
||||
}
|
||||
|
||||
size = fread(sh_table, 1, section_header_size, felf);
|
||||
if (size != section_header_size) {
|
||||
fprintf(stderr, "%s: Can't read section header: %lx/%lx\n",
|
||||
argv[0], size, section_header_size);
|
||||
free(sh_table);
|
||||
fclose(felf);
|
||||
return 27;
|
||||
}
|
||||
|
||||
sh_size = sh_table[header.e_shstrndx].sh_size;
|
||||
debug("e_shstrndx %x, sh_size %lx\n", header.e_shstrndx, sh_size);
|
||||
|
||||
sh_str = malloc(sh_size);
|
||||
if (!sh_str) {
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
free(sh_table);
|
||||
fclose(felf);
|
||||
return 28;
|
||||
}
|
||||
|
||||
/*
|
||||
* Specifies the byte offset from the beginning of the file
|
||||
* to the first byte in the section.
|
||||
*/
|
||||
sh_offset = sh_table[header.e_shstrndx].sh_offset;
|
||||
|
||||
debug("sh_offset %x\n", header.e_shnum);
|
||||
|
||||
ret = fseek(felf, sh_offset, SEEK_SET);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Setting up sh_offset failed\n");
|
||||
free(sh_str);
|
||||
free(sh_table);
|
||||
fclose(felf);
|
||||
return 29;
|
||||
}
|
||||
|
||||
size = fread(sh_str, 1, sh_size, felf);
|
||||
if (size != sh_size) {
|
||||
fprintf(stderr, "%s: Can't read section: %lx/%lx\n",
|
||||
argv[0], size, sh_size);
|
||||
free(sh_str);
|
||||
free(sh_table);
|
||||
fclose(felf);
|
||||
return 30;
|
||||
}
|
||||
|
||||
for (i = 0; i < header.e_shnum; i++) {
|
||||
debug("%s\n", sh_str + sh_table[i].sh_name);
|
||||
if (!strcmp(".rela.dyn", (sh_str + sh_table[i].sh_name))) {
|
||||
debug("Found section\t\".rela_dyn\"\n");
|
||||
debug(" at addr\t0x%08x\n", (unsigned int)sh_table[i].sh_addr);
|
||||
debug(" at offset\t0x%08x\n", (unsigned int)sh_table[i].sh_offset);
|
||||
debug(" of size\t0x%08x\n", (unsigned int)sh_table[i].sh_size);
|
||||
rela_start = sh_table[i].sh_addr;
|
||||
rela_end = rela_start + sh_table[i].sh_size;
|
||||
}
|
||||
if (!strcmp(".dynsym", (sh_str + sh_table[i].sh_name))) {
|
||||
debug("Found section\t\".dynsym\"\n");
|
||||
debug(" at addr\t0x%08x\n", (unsigned int)sh_table[i].sh_addr);
|
||||
debug(" at offset\t0x%08x\n", (unsigned int)sh_table[i].sh_offset);
|
||||
debug(" of size\t0x%08x\n", (unsigned int)sh_table[i].sh_size);
|
||||
dyn_start = sh_table[i].sh_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
free(sh_str);
|
||||
free(sh_table);
|
||||
fclose(felf);
|
||||
|
||||
debug("text_base\t0x%08lx\n", text_base);
|
||||
debug("rela_start\t0x%08lx\n", rela_start);
|
||||
debug("rela_end\t0x%08lx\n", rela_end);
|
||||
debug("dyn_start\t0x%08lx\n", dyn_start);
|
||||
|
||||
if (!rela_start)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_elf(char **argv)
|
||||
{
|
||||
FILE *felf;
|
||||
size_t size;
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
|
||||
felf = fopen(argv[2], "r+b");
|
||||
if (!felf) {
|
||||
fprintf(stderr, "%s: Cannot open %s: %s\n",
|
||||
argv[0], argv[1], strerror(errno));
|
||||
argv[0], argv[5], strerror(errno));
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (!read_num(argv[2], &text_base) ||
|
||||
!read_num(argv[3], &rela_start) ||
|
||||
!read_num(argv[4], &rela_end)) {
|
||||
fprintf(stderr, "%s: bad number\n", argv[0]);
|
||||
return 3;
|
||||
size = fread(e_ident, 1, EI_NIDENT, felf);
|
||||
if (size != EI_NIDENT) {
|
||||
fclose(felf);
|
||||
return 25;
|
||||
}
|
||||
|
||||
if (rela_start > rela_end || rela_start < text_base) {
|
||||
fprintf(stderr, "%s: bad rela bounds\n", argv[0]);
|
||||
return 3;
|
||||
/* Check if this is really ELF file */
|
||||
if (e_ident[0] != 0x7f &&
|
||||
e_ident[1] != 'E' &&
|
||||
e_ident[2] != 'L' &&
|
||||
e_ident[3] != 'F') {
|
||||
fclose(felf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rela_start -= text_base;
|
||||
rela_end -= text_base;
|
||||
ei_class = e_ident[4];
|
||||
debug("EI_CLASS(1=32bit, 2=64bit) %d\n", ei_class);
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
file_size = ftell(f);
|
||||
rewind(f);
|
||||
if (ei_class == 2)
|
||||
return decode_elf64(felf, argv);
|
||||
|
||||
if (rela_end > file_size) {
|
||||
// Most likely compiler inserted some section that didn't get
|
||||
// objcopy-ed into the final binary
|
||||
rela_end = file_size;
|
||||
}
|
||||
return decode_elf32(felf, argv);
|
||||
}
|
||||
|
||||
static int rela_elf64(char **argv, FILE *f)
|
||||
{
|
||||
int i, num;
|
||||
|
||||
if ((rela_end - rela_start) % sizeof(Elf64_Rela)) {
|
||||
fprintf(stderr, "%s: rela size isn't a multiple of Elf64_Rela\n", argv[0]);
|
||||
|
@ -161,11 +417,228 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool supported_rela32(Elf32_Rela *rela, uint32_t *type)
|
||||
{
|
||||
uint32_t mask = 0xffULL; /* would be different on 32-bit */
|
||||
*type = rela->r_info & mask;
|
||||
|
||||
debug("Type:\t");
|
||||
|
||||
switch (*type) {
|
||||
case R_MICROBLAZE_32:
|
||||
debug("R_MICROBLAZE_32\n");
|
||||
return true;
|
||||
case R_MICROBLAZE_GLOB_DAT:
|
||||
debug("R_MICROBLAZE_GLOB_DAT\n");
|
||||
return true;
|
||||
case R_MICROBLAZE_NONE:
|
||||
debug("R_MICROBLAZE_NONE - ignoring - do nothing\n");
|
||||
return false;
|
||||
case R_MICROBLAZE_REL:
|
||||
debug("R_MICROBLAZE_REL\n");
|
||||
return true;
|
||||
default:
|
||||
fprintf(stderr, "warning: unsupported relocation type %"
|
||||
PRIu32 " at %" PRIx32 "\n", *type, rela->r_offset);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int rela_elf32(char **argv, FILE *f)
|
||||
{
|
||||
int i, num, index;
|
||||
uint32_t value, type;
|
||||
|
||||
if ((rela_end - rela_start) % sizeof(Elf32_Rela)) {
|
||||
fprintf(stderr, "%s: rela size isn't a multiple of Elf32_Rela\n", argv[0]);
|
||||
return 3;
|
||||
}
|
||||
|
||||
num = (rela_end - rela_start) / sizeof(Elf32_Rela);
|
||||
|
||||
debug("Number of entries: %u\n", num);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
Elf32_Rela rela, swrela;
|
||||
Elf32_Sym symbols;
|
||||
uint32_t pos = rela_start + sizeof(Elf32_Rela) * i;
|
||||
uint32_t addr, pos_dyn;
|
||||
|
||||
debug("\nPossition:\t%d/0x%x\n", i, pos);
|
||||
|
||||
if (fseek(f, pos, SEEK_SET) < 0) {
|
||||
fprintf(stderr, "%s: %s: seek to %" PRIx32
|
||||
" failed: %s\n",
|
||||
argv[0], argv[1], pos, strerror(errno));
|
||||
}
|
||||
|
||||
if (fread(&rela, sizeof(rela), 1, f) != 1) {
|
||||
fprintf(stderr, "%s: %s: read rela failed at %"
|
||||
PRIx32 "\n",
|
||||
argv[0], argv[1], pos);
|
||||
return 4;
|
||||
}
|
||||
|
||||
debug("Rela:\toffset:\t%" PRIx32 " r_info:\t%"
|
||||
PRIu32 " r_addend:\t%" PRIx32 "\n",
|
||||
rela.r_offset, rela.r_info, rela.r_addend);
|
||||
|
||||
swrela.r_offset = cpu_to_le32(rela.r_offset);
|
||||
swrela.r_info = cpu_to_le32(rela.r_info);
|
||||
swrela.r_addend = cpu_to_le32(rela.r_addend);
|
||||
|
||||
debug("SWRela:\toffset:\t%" PRIx32 " r_info:\t%"
|
||||
PRIu32 " r_addend:\t%" PRIx32 "\n",
|
||||
swrela.r_offset, swrela.r_info, swrela.r_addend);
|
||||
|
||||
if (!supported_rela32(&swrela, &type))
|
||||
continue;
|
||||
|
||||
if (swrela.r_offset < text_base) {
|
||||
fprintf(stderr, "%s: %s: bad rela at %" PRIx32 "\n",
|
||||
argv[0], argv[1], pos);
|
||||
return 4;
|
||||
}
|
||||
|
||||
addr = swrela.r_offset - text_base;
|
||||
|
||||
debug("Addr:\t0x%" PRIx32 "\n", addr);
|
||||
|
||||
switch (type) {
|
||||
case R_MICROBLAZE_REL:
|
||||
if (fseek(f, addr, SEEK_SET) < 0) {
|
||||
fprintf(stderr, "%s: %s: seek to %"
|
||||
PRIx32 " failed: %s\n",
|
||||
argv[0], argv[1], addr, strerror(errno));
|
||||
return 5;
|
||||
}
|
||||
|
||||
debug("Write addend\n");
|
||||
|
||||
if (fwrite(&rela.r_addend, sizeof(rela.r_addend), 1, f) != 1) {
|
||||
fprintf(stderr, "%s: %s: write failed at %" PRIx32 "\n",
|
||||
argv[0], argv[1], addr);
|
||||
return 4;
|
||||
}
|
||||
break;
|
||||
case R_MICROBLAZE_32:
|
||||
case R_MICROBLAZE_GLOB_DAT:
|
||||
/* global symbols read it and add reloc offset */
|
||||
index = swrela.r_info >> 8;
|
||||
pos_dyn = dyn_start + sizeof(Elf32_Sym) * index;
|
||||
|
||||
debug("Index:\t%d\n", index);
|
||||
debug("Pos_dyn:\t0x%x\n", pos_dyn);
|
||||
|
||||
if (fseek(f, pos_dyn, SEEK_SET) < 0) {
|
||||
fprintf(stderr, "%s: %s: seek to %"
|
||||
PRIx32 " failed: %s\n",
|
||||
argv[0], argv[1], pos_dyn, strerror(errno));
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (fread(&symbols, sizeof(symbols), 1, f) != 1) {
|
||||
fprintf(stderr, "%s: %s: read symbols failed at %"
|
||||
PRIx32 "\n",
|
||||
argv[0], argv[1], pos_dyn);
|
||||
return 4;
|
||||
}
|
||||
|
||||
debug("Symbol description:\n");
|
||||
debug(" st_name:\t0x%x\n", symbols.st_name);
|
||||
debug(" st_value:\t0x%x\n", symbols.st_value);
|
||||
debug(" st_size:\t0x%x\n", symbols.st_size);
|
||||
|
||||
value = swrela.r_addend + symbols.st_value;
|
||||
|
||||
debug("Value:\t0x%x\n", value);
|
||||
|
||||
if (fseek(f, addr, SEEK_SET) < 0) {
|
||||
fprintf(stderr, "%s: %s: seek to %"
|
||||
PRIx32 " failed: %s\n",
|
||||
argv[0], argv[1], addr, strerror(errno));
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (fwrite(&value, sizeof(rela.r_addend), 1, f) != 1) {
|
||||
fprintf(stderr, "%s: %s: write failed at %" PRIx32 "\n",
|
||||
argv[0], argv[1], addr);
|
||||
return 4;
|
||||
}
|
||||
|
||||
break;
|
||||
case R_MICROBLAZE_NONE:
|
||||
debug("R_MICROBLAZE_NONE - skip\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "warning: unsupported relocation type %"
|
||||
PRIu32 " at %" PRIx32 "\n",
|
||||
type, rela.r_offset);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *f;
|
||||
int ret;
|
||||
uint64_t file_size;
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Statically apply ELF rela relocations\n");
|
||||
fprintf(stderr, "Usage: %s <bin file> <u-boot ELF>\n",
|
||||
argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = decode_elf(argv);
|
||||
if (ret) {
|
||||
fprintf(stderr, "ELF decoding failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rela_start > rela_end || rela_start < text_base) {
|
||||
fprintf(stderr, "%s: bad rela bounds\n", argv[0]);
|
||||
return 3;
|
||||
}
|
||||
|
||||
rela_start -= text_base;
|
||||
rela_end -= text_base;
|
||||
dyn_start -= text_base;
|
||||
|
||||
f = fopen(argv[1], "r+b");
|
||||
if (!f) {
|
||||
fprintf(stderr, "%s: Cannot open %s: %s\n",
|
||||
argv[0], argv[1], strerror(errno));
|
||||
return 2;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
file_size = ftell(f);
|
||||
rewind(f);
|
||||
|
||||
if (rela_end > file_size) {
|
||||
// Most likely compiler inserted some section that didn't get
|
||||
// objcopy-ed into the final binary
|
||||
rela_end = file_size;
|
||||
}
|
||||
|
||||
if (ei_class == 2)
|
||||
ret = rela_elf64(argv, f);
|
||||
else
|
||||
ret = rela_elf32(argv, f);
|
||||
|
||||
if (fclose(f) < 0) {
|
||||
fprintf(stderr, "%s: %s: close failed: %s\n",
|
||||
argv[0], argv[1], strerror(errno));
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (C) 2018 Michal Simek <michal.simek@xilinx.com>
|
||||
# Copyright (C) 2019 Luca Ceresoli <luca@lucaceresoli.net>
|
||||
# Copyright (C) 2022 Weidmüller Interface GmbH & Co. KG
|
||||
# Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
|
||||
|
||||
usage()
|
||||
{
|
||||
|
@ -119,7 +121,7 @@ tr "\n" "\r" <${OUT} >${TMP}
|
|||
# | | ==> |while (e)|
|
||||
# | } | | ; |
|
||||
# | |
|
||||
sed -i -r 's| \{\r+(\t*)\}\r\r|\n\1\t;\n|g' ${TMP}
|
||||
sed -i -r 's| \{\r+(\t*)\}\r\r|\r\1\t;\r|g' ${TMP}
|
||||
|
||||
# Remove empty line between variable declaration
|
||||
sed -i -r 's|\r(\r\t(unsigned )?int )|\1|g' ${TMP}
|
||||
|
@ -141,7 +143,30 @@ sed -i -r 's| \{(\r[^\r]*;)\r\t*\}|\1|g' ${TMP}
|
|||
# if ((p_code >= 0x26) && ...) -> if (p_code >= 0x26 && ...)
|
||||
sed -i -r 's|\((._code .= [x[:xdigit:]]+)\)|\1|g' ${TMP}
|
||||
|
||||
# Move helper functions below header includes
|
||||
TARGET="#include <xil_io.h>"
|
||||
START="static int serdes_rst_seq"
|
||||
END="static int serdes_enb_coarse_saturation"
|
||||
|
||||
sed -i -e "s|\(${TARGET}\r\r\)\(.*\)\(${START}(.*\)\(${END}(\)|\1\3\2\4|g" \
|
||||
${TMP}
|
||||
|
||||
# Convert back newlines
|
||||
tr "\r" "\n" <${TMP} >${OUT}
|
||||
|
||||
# Remove unnecessary settings
|
||||
# - Low level UART
|
||||
SETTINGS_TO_REMOVE="0xFF000000
|
||||
0xFF000004
|
||||
0xFF000018
|
||||
0xFF000034
|
||||
0xFF010000
|
||||
0xFF010004
|
||||
0xFF010018
|
||||
0xFF010034
|
||||
"
|
||||
for i in $SETTINGS_TO_REMOVE; do
|
||||
sed -i "/^\tpsu_mask_write($i,.*$/d" ${OUT}
|
||||
done
|
||||
|
||||
rm ${TMP}
|
||||
|
|
Loading…
Reference in New Issue
Block a user