i.MX for 2020.07

----------------
 
 - i.MX NAND and nandbxb for i.MX8M
 - imx8MM : new beacon devkit
 - imx8MQ : new pico-imx8MQ
 - imx8QXP : extend to enable M4, fixes
 - add thermal support
 - caches in SPL (missing board)
 - Fixes
 
 Travis: https://travis-ci.org/github/sbabic/u-boot-imx/builds/685391011
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQS2TmnA27QKhpKSZe309WXkmmjvpgUCXrklRA8cc2JhYmljQGRl
 bnguZGUACgkQ9PVl5Jpo76bO5ACdH8huXVOBT5dHlzJYJcHo1YaLh9sAmwezO44z
 oNDJdyyEugycwU3zpqyd
 =e0Zc
 -----END PGP SIGNATURE-----

Merge tag 'u-boot-imx-20200511' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx

i.MX for 2020.07
----------------

- i.MX NAND and nandbxb for i.MX8M
- imx8MM : new beacon devkit
- imx8MQ : new pico-imx8MQ
- imx8QXP : extend to enable M4, fixes
- add thermal support
- caches in SPL (missing board)
- Fixes

Travis: https://travis-ci.org/github/sbabic/u-boot-imx/builds/685391011
This commit is contained in:
Tom Rini 2020-05-11 09:46:43 -04:00
commit 1bccb23b7b
99 changed files with 14975 additions and 378 deletions

View file

@ -76,6 +76,12 @@ config SPL_ARMV8_SEC_FIRMWARE_SUPPORT
help
Say Y here to support this framework in SPL phase.
config SPL_RECOVER_DATA_SECTION
bool "save/restore SPL data section"
help
Say Y here to save SPL data section for cold boot, and restore
at warm boot in SPL phase.
config SEC_FIRMWARE_ARMV8_PSCI
bool "PSCI implementation in secure monitor firmware"
depends on ARMV8_SEC_FIRMWARE_SUPPORT || SPL_ARMV8_SEC_FIRMWARE_SUPPORT

View file

@ -30,6 +30,10 @@ obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o
endif
obj-$(CONFIG_$(SPL_)ARMV8_SEC_FIRMWARE_SUPPORT) += sec_firmware.o sec_firmware_asm.o
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SPL_RECOVER_DATA_SECTION) += spl_data.o
endif
obj-$(CONFIG_FSL_LAYERSCAPE) += fsl-layerscape/
obj-$(CONFIG_S32V234) += s32v234/
obj-$(CONFIG_TARGET_HIKEY) += hisilicon/

View file

@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2020 NXP
*/
#include <common.h>
#include <spl.h>
char __data_save_start[0] __section(.__data_save_start);
char __data_save_end[0] __section(.__data_save_end);
u32 cold_reboot_flag = 1;
void spl_save_restore_data(void)
{
u32 data_size = __data_save_end - __data_save_start;
if (cold_reboot_flag == 1) {
/* Save data section to data_save section */
memcpy(__data_save_start, __data_save_start - data_size,
data_size);
} else {
/* Restore the data_save section to data section */
memcpy(__data_save_start - data_size, __data_save_start,
data_size);
}
cold_reboot_flag++;
}

View file

@ -38,6 +38,14 @@ SECTIONS
*(.data*)
} >.sram
#ifdef CONFIG_SPL_RECOVER_DATA_SECTION
.data_save : {
*(.__data_save_start)
. = SIZEOF(.data);
*(.__data_save_end)
} >.sram
#endif
.u_boot_list : {
. = ALIGN(8);
KEEP(*(SORT(.u_boot_list*)));

View file

@ -736,8 +736,10 @@ dtb-$(CONFIG_ARCH_IMX8M) += \
imx8mm-verdin.dtb \
imx8mn-ddr4-evk.dtb \
imx8mq-evk.dtb \
imx8mm-beacon-kit.dtb \
imx8mq-phanbell.dtb \
imx8mp-evk.dtb
imx8mp-evk.dtb \
imx8mq-pico-pi.dtb
dtb-$(CONFIG_ARCH_IMXRT) += imxrt1050-evk.dtb \
imxrt1020-evk.dtb

View file

@ -131,7 +131,7 @@
pd_lsio: PD_LSIO {
compatible = "nxp,imx8-pd";
reg = <SC_R_LAST>;
reg = <SC_R_NONE>;
#power-domain-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
@ -180,7 +180,7 @@
pd_conn: PD_CONN {
compatible = "nxp,imx8-pd";
reg = <SC_R_LAST>;
reg = <SC_R_NONE>;
#power-domain-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
@ -214,7 +214,7 @@
pd_dma: PD_DMA {
compatible = "nxp,imx8-pd";
reg = <SC_R_LAST>;
reg = <SC_R_NONE>;
#power-domain-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;

View file

@ -88,7 +88,7 @@
pd_lsio: PD_LSIO {
compatible = "nxp,imx8-pd";
reg = <SC_R_LAST>;
reg = <SC_R_NONE>;
#power-domain-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
@ -137,7 +137,7 @@
pd_conn: PD_CONN {
compatible = "nxp,imx8-pd";
reg = <SC_R_LAST>;
reg = <SC_R_NONE>;
#power-domain-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
@ -173,7 +173,7 @@
pd_dma: PD_DMA {
compatible = "nxp,imx8-pd";
reg = <SC_R_LAST>;
reg = <SC_R_NONE>;
#power-domain-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;

View file

@ -0,0 +1,285 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright 2020 Compass Electronics Group, LLC
*/
/ {
leds {
compatible = "gpio-leds";
led0 {
label = "gen_led0";
gpios = <&pca6416_1 4 GPIO_ACTIVE_HIGH>;
default-state = "none";
};
led1 {
label = "gen_led1";
gpios = <&pca6416_1 5 GPIO_ACTIVE_HIGH>;
default-state = "none";
};
led2 {
label = "gen_led2";
gpios = <&pca6416_1 6 GPIO_ACTIVE_HIGH>;
default-state = "none";
};
led3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_led3>;
label = "heartbeat";
gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
};
reg_audio: regulator-audio {
compatible = "regulator-fixed";
regulator-name = "3v3_aud";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&pca6416_1 11 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
reg_usdhc2_vmmc: regulator-usdhc2 {
compatible = "regulator-fixed";
regulator-name = "VSD_3V3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
sound {
compatible = "fsl,imx-audio-wm8962";
model = "wm8962-audio";
audio-cpu = <&sai3>;
audio-codec = <&wm8962>;
audio-routing =
"Headphone Jack", "HPOUTL",
"Headphone Jack", "HPOUTR",
"Ext Spk", "SPKOUTL",
"Ext Spk", "SPKOUTR",
"AMIC", "MICBIAS",
"IN3R", "AMIC";
};
};
&ecspi2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_espi2>;
cs-gpios = <&gpio5 9 0>;
status = "okay";
eeprom@0 {
compatible = "microchip,at25160bn", "atmel,at25";
reg = <0>;
spi-max-frequency = <5000000>;
spi-cpha;
spi-cpol;
pagesize = <32>;
size = <2048>;
address-width = <16>;
};
};
&i2c2 {
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
};
&i2c4 {
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c4>;
status = "okay";
wm8962: audio-codec@1a {
compatible = "wlf,wm8962";
reg = <0x1a>;
clocks = <&clk IMX8MM_CLK_SAI3_ROOT>;
clock-names = "xclk";
DCVDD-supply = <&reg_audio>;
DBVDD-supply = <&reg_audio>;
AVDD-supply = <&reg_audio>;
CPVDD-supply = <&reg_audio>;
MICVDD-supply = <&reg_audio>;
PLLVDD-supply = <&reg_audio>;
SPKVDD1-supply = <&reg_audio>;
SPKVDD2-supply = <&reg_audio>;
gpio-cfg = <
0x0000 /* 0:Default */
0x0000 /* 1:Default */
0x0000 /* 2:FN_DMICCLK */
0x0000 /* 3:Default */
0x0000 /* 4:FN_DMICCDAT */
0x0000 /* 5:Default */
>;
};
pca6416_0: gpio@20 {
compatible = "nxp,pcal6416";
reg = <0x20>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pcal6414>;
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&gpio4>;
interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
};
pca6416_1: gpio@21 {
compatible = "nxp,pcal6416";
reg = <0x21>;
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&gpio4>;
interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
};
};
&sai3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai3>;
assigned-clocks = <&clk IMX8MM_CLK_SAI3>;
assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
assigned-clock-rates = <24576000>;
fsl,sai-mclk-direction-output;
status = "okay";
};
&snvs_pwrkey {
status = "okay";
};
&uart2 { /* console */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2>;
status = "okay";
};
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart3>;
assigned-clocks = <&clk IMX8MM_CLK_UART3>;
assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
status = "okay";
};
&usdhc2 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
bus-width = <4>;
vmmc-supply = <&reg_usdhc2_vmmc>;
status = "okay";
};
&iomuxc {
pinctrl_espi2: espi2grp {
fsl,pins = <
MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0x82
MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0x82
MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0x82
MX8MM_IOMUXC_ECSPI1_SS0_GPIO5_IO9 0x41
>;
};
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA 0x400001c3
>;
};
pinctrl_i2c4: i2c4grp {
fsl,pins = <
MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c3
MX8MM_IOMUXC_I2C4_SDA_I2C4_SDA 0x400001c3
>;
};
pinctrl_led3: led3grp {
fsl,pins = <
MX8MM_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x41
>;
};
pinctrl_pcal6414: pcal6414-gpio {
fsl,pins = <
MX8MM_IOMUXC_SAI2_MCLK_GPIO4_IO27 0x19
>;
};
pinctrl_sai3: sai3grp {
fsl,pins = <
MX8MM_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC 0xd6
MX8MM_IOMUXC_SAI3_TXC_SAI3_TX_BCLK 0xd6
MX8MM_IOMUXC_SAI3_MCLK_SAI3_MCLK 0xd6
MX8MM_IOMUXC_SAI3_TXD_SAI3_TX_DATA0 0xd6
MX8MM_IOMUXC_SAI3_RXD_SAI3_RX_DATA0 0xd6
>;
};
pinctrl_uart2: uart2grp {
fsl,pins = <
MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140
MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140
>;
};
pinctrl_uart3: uart3grp {
fsl,pins = <
MX8MM_IOMUXC_ECSPI1_SCLK_UART3_DCE_RX 0x40
MX8MM_IOMUXC_ECSPI1_MOSI_UART3_DCE_TX 0x40
>;
};
pinctrl_usdhc2_gpio: usdhc2grpgpio {
fsl,pins = <
MX8MM_IOMUXC_SD2_CD_B_USDHC2_CD_B 0x41
MX8MM_IOMUXC_SD2_RESET_B_GPIO2_IO19 0x41
>;
};
pinctrl_usdhc2: usdhc2grp {
fsl,pins = <
MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x190
MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d0
MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d0
MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d0
MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d0
MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d0
MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
>;
};
pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
fsl,pins = <
MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x194
MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d4
MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d4
MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d4
MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d4
MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d4
MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
>;
};
pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
fsl,pins = <
MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x196
MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d6
MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d6
MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d6
MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d6
MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d6
MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
>;
};
};

View file

@ -0,0 +1,131 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2020 Compass Electronics Group, LLC
*/
/ {
wdt-reboot {
compatible = "wdt-reboot";
wdt = <&wdog1>;
u-boot,dm-spl;
};
};
&{/soc@0} {
u-boot,dm-pre-reloc;
u-boot,dm-spl;
};
&aips1 {
u-boot,dm-spl;
u-boot,dm-pre-reloc;
};
&aips2 {
u-boot,dm-spl;
};
&aips3 {
u-boot,dm-spl;
};
&clk {
u-boot,dm-spl;
u-boot,dm-pre-reloc;
/delete-property/ assigned-clocks;
/delete-property/ assigned-clock-parents;
/delete-property/ assigned-clock-rates;
};
&fec1 {
phy-reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>;
};
&gpio1 {
u-boot,dm-spl;
};
&gpio2 {
u-boot,dm-spl;
};
&gpio3 {
u-boot,dm-spl;
};
&gpio4 {
u-boot,dm-spl;
};
&gpio5 {
u-boot,dm-spl;
};
&iomuxc {
u-boot,dm-spl;
};
&osc_24m {
u-boot,dm-spl;
u-boot,dm-pre-reloc;
};
&pca6416_0 {
compatible = "ti,tca6416";
};
&pca6416_1 {
compatible = "ti,tca6416";
};
&pinctrl_i2c1 {
u-boot,dm-spl;
};
&pinctrl_pmic {
u-boot,dm-spl;
};
&pinctrl_uart2 {
u-boot,dm-spl;
};
&pinctrl_usdhc2_gpio {
u-boot,dm-spl;
};
&pinctrl_usdhc2 {
u-boot,dm-spl;
};
&pinctrl_usdhc3 {
u-boot,dm-spl;
};
&uart2 {
u-boot,dm-spl;
};
&usdhc2 {
u-boot,dm-spl;
};
&usdhc3 {
u-boot,dm-spl;
};
&i2c1 {
u-boot,dm-spl;
};
&{/soc@0/bus@30800000/i2c@30a20000/pmic@4b} {
u-boot,dm-spl;
};
&{/soc@0/bus@30800000/i2c@30a20000/pmic@4b/regulators} {
u-boot,dm-spl;
};
&wdog1 {
u-boot,dm-spl;
};

View file

@ -0,0 +1,19 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright 2020 Compass Electronics Group, LLC
*/
/dts-v1/;
#include "imx8mm.dtsi"
#include "imx8mm-beacon-som.dtsi"
#include "imx8mm-beacon-baseboard.dtsi"
/ {
model = "Beacon EmbeddedWorks i.MX8M Mini Development Kit";
compatible = "beacon,imx8mm-beacon-kit", "fsl,imx8mm";
chosen {
stdout-path = &uart2;
};
};

View file

@ -0,0 +1,390 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright 2020 Compass Electronics Group, LLC
*/
/ {
usdhc1_pwrseq: usdhc1_pwrseq {
compatible = "mmc-pwrseq-simple";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc1_gpio>;
reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
clocks = <&osc_32k>;
clock-names = "ext_clock";
post-power-on-delay-ms = <80>;
};
memory@40000000 {
device_type = "memory";
reg = <0x0 0x40000000 0 0x80000000>;
};
};
&A53_0 {
cpu-supply = <&buck2_reg>;
};
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_fec1>;
phy-mode = "rgmii-id";
phy-handle = <&ethphy0>;
fsl,magic-packet;
status = "okay";
mdio {
#address-cells = <1>;
#size-cells = <0>;
ethphy0: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <0>;
};
};
};
&i2c1 {
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
status = "okay";
pmic@4b {
compatible = "rohm,bd71847";
reg = <0x4b>;
pinctrl-0 = <&pinctrl_pmic>;
interrupt-parent = <&gpio1>;
interrupts = <3 GPIO_ACTIVE_LOW>;
rohm,reset-snvs-powered;
regulators {
buck1_reg: BUCK1 {
regulator-name = "buck1";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1300000>;
regulator-boot-on;
regulator-always-on;
regulator-ramp-delay = <1250>;
};
buck2_reg: BUCK2 {
regulator-name = "buck2";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1300000>;
regulator-boot-on;
regulator-always-on;
regulator-ramp-delay = <1250>;
rohm,dvs-run-voltage = <1000000>;
rohm,dvs-idle-voltage = <900000>;
};
buck3_reg: BUCK3 {
// BUCK5 in datasheet
regulator-name = "buck3";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1350000>;
regulator-boot-on;
regulator-always-on;
};
buck4_reg: BUCK4 {
// BUCK6 in datasheet
regulator-name = "buck4";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
buck5_reg: BUCK5 {
// BUCK7 in datasheet
regulator-name = "buck5";
regulator-min-microvolt = <1605000>;
regulator-max-microvolt = <1995000>;
regulator-boot-on;
regulator-always-on;
};
buck6_reg: BUCK6 {
// BUCK8 in datasheet
regulator-name = "buck6";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1400000>;
regulator-boot-on;
regulator-always-on;
};
ldo1_reg: LDO1 {
regulator-name = "ldo1";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
ldo2_reg: LDO2 {
regulator-name = "ldo2";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <900000>;
regulator-boot-on;
regulator-always-on;
};
ldo3_reg: LDO3 {
regulator-name = "ldo3";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
ldo4_reg: LDO4 {
regulator-name = "ldo4";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
};
ldo6_reg: LDO6 {
regulator-name = "ldo6";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
};
};
};
};
&i2c3 {
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>;
status = "okay";
eeprom@50 {
compatible = "microchip, at24c64d", "atmel,24c64";
pagesize = <32>;
read-only; /* Manufacturing EEPROM programmed at factory */
reg = <0x50>;
};
rtc@51 {
compatible = "nxp,pcf85263";
reg = <0x51>;
};
};
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
assigned-clocks = <&clk IMX8MM_CLK_UART1>;
assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
uart-has-rtscts;
status = "okay";
bluetooth {
compatible = "brcm,bcm43438-bt";
shutdown-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
host-wakeup-gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>;
device-wakeup-gpios = <&gpio2 7 GPIO_ACTIVE_HIGH>;
clocks = <&osc_32k>;
clock-names = "extclk";
};
};
&usdhc1 {
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc1>;
bus-width = <4>;
non-removable;
cap-power-off-card;
pm-ignore-notify;
keep-power-in-suspend;
mmc-pwrseq = <&usdhc1_pwrseq>;
status = "okay";
brcmf: bcrmf@1 {
reg = <1>;
compatible = "brcm,bcm4329-fmac";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_wlan>;
interrupt-parent = <&gpio2>;
interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "host-wake";
};
};
&usdhc3 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc3>;
pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
bus-width = <8>;
non-removable;
status = "okay";
};
&wdog1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_wdog>;
fsl,ext-reset-output;
status = "okay";
};
&iomuxc {
pinctrl_fec1: fec1grp {
fsl,pins = <
MX8MM_IOMUXC_ENET_MDC_ENET1_MDC 0x3
MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO 0x3
MX8MM_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
MX8MM_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
MX8MM_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
MX8MM_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
MX8MM_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
MX8MM_IOMUXC_SAI2_RXC_GPIO4_IO22 0x19
>;
};
pinctrl_i2c1: i2c1grp {
fsl,pins = <
MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL 0x400001c3
MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA 0x400001c3
>;
};
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA 0x400001c3
>;
};
pinctrl_pmic: pmicirq {
fsl,pins = <
MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41
>;
};
pinctrl_uart1: uart1grp {
fsl,pins = <
MX8MM_IOMUXC_UART1_RXD_UART1_DCE_RX 0x140
MX8MM_IOMUXC_UART1_TXD_UART1_DCE_TX 0x140
MX8MM_IOMUXC_UART3_RXD_UART1_DCE_CTS_B 0x140
MX8MM_IOMUXC_UART3_TXD_UART1_DCE_RTS_B 0x140
MX8MM_IOMUXC_SD1_DATA4_GPIO2_IO6 0x19
MX8MM_IOMUXC_SD1_DATA5_GPIO2_IO7 0x19
MX8MM_IOMUXC_SD1_DATA6_GPIO2_IO8 0x19
MX8MM_IOMUXC_GPIO1_IO00_ANAMIX_REF_CLK_32K 0x141
>;
};
pinctrl_usdhc1_gpio: usdhc1grpgpio {
fsl,pins = <
MX8MM_IOMUXC_SD1_RESET_B_GPIO2_IO10 0x41
>;
};
pinctrl_usdhc1: usdhc1grp {
fsl,pins = <
MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x190
MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d0
MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d0
MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d0
MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d0
MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d0
>;
};
pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
fsl,pins = <
MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x194
MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d4
MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d4
MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d4
MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d4
MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d4
>;
};
pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
fsl,pins = <
MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x196
MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d6
MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d6
MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d6
MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d6
MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d6
>;
};
pinctrl_usdhc3: usdhc3grp {
fsl,pins = <
MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x190
MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d0
MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d0
MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d0
MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d0
MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d0
MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d0
MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d0
MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d0
MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d0
MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x190
>;
};
pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
fsl,pins = <
MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x194
MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d4
MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d4
MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d4
MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d4
MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d4
MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d4
MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d4
MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d4
MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d4
MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x194
>;
};
pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
fsl,pins = <
MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x196
MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d6
MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d6
MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d6
MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d6
MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d6
MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d6
MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d6
MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d6
MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d6
MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x196
>;
};
pinctrl_wdog: wdoggrp {
fsl,pins = <
MX8MM_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
>;
};
pinctrl_wlan: wlangrp {
fsl,pins = <
MX8MM_IOMUXC_SD1_DATA7_GPIO2_IO9 0x111
>;
};
};

View file

@ -0,0 +1,420 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018 Wandboard, Org.
* Copyright 2017 NXP
*
* Author: Richard Hu <hakahu@gmail.com>
*/
/dts-v1/;
#include "imx8mq.dtsi"
/ {
model = "TechNexion PICO-PI-8M";
compatible = "technexion,pico-pi-imx8m", "fsl,imx8mq";
chosen {
stdout-path = &uart1;
};
pmic_osc: clock-pmic {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
clock-output-names = "pmic_osc";
};
reg_usb_otg_vbus: regulator-usb-otg-vbus {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_otg_vbus>;
compatible = "regulator-fixed";
regulator-name = "usb_otg_vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio3 14 GPIO_ACTIVE_LOW>;
};
reg_eth_phy: eth_phy {
compatible = "regulator-fixed";
regulator-name = "eth_phy_pwr";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio1 0 GPIO_ACTIVE_HIGH>;
};
};
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_fec1>;
phy-mode = "rgmii-id";
phy-handle = <&ethphy0>;
phy-supply = <&reg_eth_phy>;
phy-reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
phy-reset-duration = <100>;
phy-reset-post-delay = <100>;
fsl,magic-packet;
status = "okay";
mdio {
#address-cells = <1>;
#size-cells = <0>;
ethphy0: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <1>;
};
};
};
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
status = "okay";
pmic: pmic@4b {
reg = <0x4b>;
compatible = "rohm,bd71837";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pmic>;
clocks = <&pmic_osc>;
clock-names = "osc";
clock-output-names = "pmic_clk";
interrupt-parent = <&gpio1>;
interrupts = <3 GPIO_ACTIVE_LOW>;
interrupt-names = "irq";
regulators {
buck1: BUCK1 {
regulator-name = "buck1";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1300000>;
regulator-boot-on;
regulator-ramp-delay = <1250>;
rohm,dvs-run-voltage = <900000>;
rohm,dvs-idle-voltage = <850000>;
rohm,dvs-suspend-voltage = <800000>;
};
buck2: BUCK2 {
regulator-name = "buck2";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1300000>;
regulator-boot-on;
regulator-ramp-delay = <1250>;
rohm,dvs-run-voltage = <1000000>;
rohm,dvs-idle-voltage = <900000>;
};
buck3: BUCK3 {
regulator-name = "buck3";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1300000>;
regulator-boot-on;
rohm,dvs-run-voltage = <1000000>;
};
buck4: BUCK4 {
regulator-name = "buck4";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1300000>;
regulator-boot-on;
rohm,dvs-run-voltage = <1000000>;
};
buck5: BUCK5 {
regulator-name = "buck5";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1350000>;
regulator-boot-on;
};
buck6: BUCK6 {
regulator-name = "buck6";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
};
buck7: BUCK7 {
regulator-name = "buck7";
regulator-min-microvolt = <1605000>;
regulator-max-microvolt = <1995000>;
regulator-boot-on;
};
buck8: BUCK8 {
regulator-name = "buck8";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1400000>;
regulator-boot-on;
};
ldo1: LDO1 {
regulator-name = "ldo1";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
ldo2: LDO2 {
regulator-name = "ldo2";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <900000>;
regulator-boot-on;
regulator-always-on;
};
ldo3: LDO3 {
regulator-name = "ldo3";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
};
ldo4: LDO4 {
regulator-name = "ldo4";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
};
ldo5: LDO5 {
regulator-name = "ldo5";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
};
ldo6: LDO6 {
regulator-name = "ldo6";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
};
ldo7: LDO7 {
regulator-name = "ldo7";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
};
};
};
};
&i2c2 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
};
&uart1 { /* console */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
status = "okay";
};
&usdhc1 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc1>;
pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
bus-width = <8>;
non-removable;
status = "okay";
};
&usdhc2 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
bus-width = <4>;
cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
status = "okay";
};
&usb3_phy0 {
status = "okay";
};
&usb3_phy1 {
status = "okay";
};
&usb_dwc3_1 {
dr_mode = "host";
status = "okay";
};
&wdog1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_wdog>;
fsl,ext-reset-output;
status = "okay";
};
&iomuxc {
pinctrl_fec1: fec1grp {
fsl,pins = <
MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3
MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23
MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
MX8MQ_IOMUXC_GPIO1_IO00_GPIO1_IO0 0x19
MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19
>;
};
pinctrl_i2c1: i2c1grp {
fsl,pins = <
MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f
MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f
>;
};
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL 0x4000007f
MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA 0x4000007f
>;
};
pinctrl_otg_vbus: otgvbusgrp {
fsl,pins = <
MX8MQ_IOMUXC_NAND_DQS_GPIO3_IO14 0x19 /* USB OTG VBUS Enable */
>;
};
pinctrl_pmic: pmicirq {
fsl,pins = <
MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41
>;
};
pinctrl_uart1: uart1grp {
fsl,pins = <
MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49
MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49
>;
};
pinctrl_uart2: uart2grp {
fsl,pins = <
MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX 0x49
MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX 0x49
MX8MQ_IOMUXC_UART4_RXD_UART2_DCE_CTS_B 0x49
MX8MQ_IOMUXC_UART4_TXD_UART2_DCE_RTS_B 0x49
>;
};
pinctrl_usdhc1: usdhc1grp {
fsl,pins = <
MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x83
MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc3
MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc3
MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc3
MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc3
MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc3
MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc3
MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc3
MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc3
MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc3
MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x83
>;
};
pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
fsl,pins = <
MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x85
MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc5
MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc5
MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc5
MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc5
MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc5
MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc5
MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc5
MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc5
MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc5
MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x85
>;
};
pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
fsl,pins = <
MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x87
MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc7
MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc7
MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc7
MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc7
MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc7
MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc7
MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc7
MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc7
MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc7
MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x87
>;
};
pinctrl_usdhc2_gpio: usdhc2grpgpio {
fsl,pins = <
MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41
>;
};
pinctrl_usdhc2: usdhc2grp {
fsl,pins = <
MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x83
MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc3
MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc3
MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc3
MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc3
MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc3
MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
>;
};
pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
fsl,pins = <
MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x85
MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc5
MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc5
MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc5
MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc5
MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc5
MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
>;
};
pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
fsl,pins = <
MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x87
MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc7
MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc7
MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc7
MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc7
MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc7
MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
>;
};
pinctrl_wdog: wdoggrp {
fsl,pins = <
MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
>;
};
};

View file

@ -64,6 +64,7 @@
#define CHIP_REV_A 0x0
#define CHIP_REV_B 0x1
#define CHIP_REV_C 0x2
#define BOARD_REV_1_0 0x0
#define BOARD_REV_2_0 0x1

View file

@ -5,6 +5,11 @@
#include <asm/arch/sci/sci.h>
#include <asm/mach-imx/sys_proto.h>
#include <asm/arch/power-domain.h>
#include <dm/platdata.h>
#include <dm/device-internal.h>
#include <dm/device.h>
#include <power-domain.h>
#include <linux/types.h>
struct pass_over_info_t {
@ -21,3 +26,7 @@ void build_info(void);
enum boot_device get_boot_device(void);
int print_bootinfo(void);
int sc_pm_setup_uart(sc_rsrc_t uart_rsrc, sc_pm_clock_rate_t clk_rate);
int imx8_power_domain_lookup_name(const char *name,
struct power_domain *power_domain);
void imx8_power_off_pd_devices(const char *permanent_on_devices[], int size);
bool m4_parts_booted(void);

View file

@ -137,6 +137,40 @@ struct fuse_bank1_regs {
u32 rsvd3[3];
};
struct fuse_bank3_regs {
u32 mem_trim0;
u32 rsvd0[3];
u32 mem_trim1;
u32 rsvd1[3];
u32 mem_trim2;
u32 rsvd2[3];
u32 ana0;
u32 rsvd3[3];
};
struct fuse_bank9_regs {
u32 mac_addr0;
u32 rsvd0[3];
u32 mac_addr1;
u32 rsvd1[11];
};
struct fuse_bank38_regs {
u32 ana_trim1; /* trim0 is at 0xD70, bank 37*/
u32 rsvd0[3];
u32 ana_trim2;
u32 rsvd1[3];
u32 ana_trim3;
u32 rsvd2[3];
u32 ana_trim4;
u32 rsvd3[3];
};
struct fuse_bank39_regs {
u32 ana_trim5;
u32 rsvd[15];
};
#ifdef CONFIG_IMX8MQ
struct anamix_pll {
u32 audio_pll1_cfg0;
@ -227,13 +261,6 @@ struct anamix_pll {
};
#endif
struct fuse_bank9_regs {
u32 mac_addr0;
u32 rsvd0[3];
u32 mac_addr1;
u32 rsvd1[11];
};
/* System Reset Controller (SRC) */
struct src {
u32 scr;

View file

@ -7,6 +7,7 @@
*
* Based on code from LTIB:
* Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2020 NXP
*/
#ifndef __DMA_H__
@ -53,7 +54,7 @@ enum {
MXS_DMA_CHANNEL_AHB_APBH_RESERVED1,
MXS_MAX_DMA_CHANNELS,
};
#elif defined(CONFIG_MX6) || defined(CONFIG_MX7)
#else
enum {
MXS_DMA_CHANNEL_AHB_APBH_GPMI0 = 0,
MXS_DMA_CHANNEL_AHB_APBH_GPMI1,
@ -95,13 +96,13 @@ enum {
#define MXS_DMA_DESC_BYTES_OFFSET 16
struct mxs_dma_cmd {
unsigned long next;
unsigned long data;
u32 next;
u32 data;
union {
dma_addr_t address;
unsigned long alternate;
u32 address;
u32 alternate;
};
unsigned long pio_words[DMA_PIO_WORDS];
u32 pio_words[DMA_PIO_WORDS];
};
/*
@ -117,7 +118,7 @@ struct mxs_dma_cmd {
struct mxs_dma_desc {
struct mxs_dma_cmd cmd;
unsigned int flags;
dma_addr_t address;
u32 address;
void *buffer;
struct list_head node;
} __aligned(MXS_DMA_ALIGNMENT);

View file

@ -9,9 +9,11 @@
#define FCB_FINGERPRINT 0x20424346 /* 'FCB' */
#define FCB_VERSION_1 0x01000000
#define FCB_FINGERPRINT_OFF 0x4 /* FCB fingerprint offset*/
#define DBBT_FINGERPRINT2 0x54424244 /* 'DBBT' */
#define DBBT_FINGERPRINT 0x54424244 /* 'DBBT' */
#define DBBT_VERSION_1 0x01000000
#define DBBT_FINGERPRINT_OFF 0x4 /* DBBT fingerprint offset*/
struct dbbt_block {
u32 checksum; /* reserved on i.MX6 */

View file

@ -0,0 +1,127 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2019 NXP
*/
#ifndef __MODULE_FUSE_H__
#define __MODULE_FUSE_H__
enum fuse_module_type {
MODULE_TSC,
MODULE_ADC1,
MODULE_ADC2,
MODULE_SIM1,
MODULE_SIM2,
MODULE_FLEXCAN1,
MODULE_FLEXCAN2,
MODULE_SPDIF,
MODULE_EIM,
MODULE_SD1,
MODULE_SD2,
MODULE_SD3,
MODULE_SD4,
MODULE_QSPI1,
MODULE_QSPI2,
MODULE_GPMI,
MODULE_APBHDMA,
MODULE_LCDIF,
MODULE_PXP,
MODULE_CSI,
MODULE_ENET1,
MODULE_ENET2,
MODULE_CAAM,
MODULE_USB_OTG1,
MODULE_USB_OTG2,
MODULE_SAI2,
MODULE_SAI3,
MODULE_BEE,
MODULE_UART1,
MODULE_UART2,
MODULE_UART3,
MODULE_UART4,
MODULE_UART5,
MODULE_UART6,
MODULE_UART7,
MODULE_UART8,
MODULE_PWM5,
MODULE_PWM6,
MODULE_PWM7,
MODULE_PWM8,
MODULE_ECSPI1,
MODULE_ECSPI2,
MODULE_ECSPI3,
MODULE_ECSPI4,
MODULE_ECSPI5,
MODULE_I2C1,
MODULE_I2C2,
MODULE_I2C3,
MODULE_I2C4,
MODULE_GPT1,
MODULE_GPT2,
MODULE_EPIT1,
MODULE_EPIT2,
MODULE_EPDC,
MODULE_ESAI,
MODULE_DCP,
MODULE_DCP_CRYPTO,
};
struct fuse_entry_desc {
enum fuse_module_type module;
const char *node_path;
u32 fuse_word_offset;
u32 fuse_bit_offset;
u32 status;
};
#if !CONFIG_IS_ENABLED(IMX_MODULE_FUSE)
static inline u32 check_module_fused(enum fuse_module_type module)
{
return 0;
};
static inline u32 esdhc_fused(ulong base_addr)
{
return 0;
};
static inline u32 ecspi_fused(ulong base_addr)
{
return 0;
};
static inline u32 uart_fused(ulong base_addr)
{
return 0;
};
static inline u32 usb_fused(ulong base_addr)
{
return 0;
};
static inline u32 qspi_fused(ulong base_addr)
{
return 0;
};
static inline u32 i2c_fused(ulong base_addr)
{
return 0;
};
static inline u32 enet_fused(ulong base_addr)
{
return 0;
};
#else
u32 check_module_fused(enum fuse_module_type module);
u32 esdhc_fused(ulong base_addr);
u32 ecspi_fused(ulong base_addr);
u32 uart_fused(ulong base_addr);
u32 usb_fused(ulong base_addr);
u32 qspi_fused(ulong base_addr);
u32 i2c_fused(ulong base_addr);
u32 enet_fused(ulong base_addr);
#endif
#endif /* __MODULE_FUSE_H__ */

View file

@ -7,6 +7,7 @@
*
* Based on code from LTIB:
* Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2020 NXP
*/
#ifndef __REGS_APBH_H__
@ -95,7 +96,7 @@ struct mxs_apbh_regs {
mxs_reg_32(hw_apbh_version)
};
#elif (defined(CONFIG_MX28) || defined(CONFIG_MX6) || defined(CONFIG_MX7))
#else
struct mxs_apbh_regs {
mxs_reg_32(hw_apbh_ctrl0)
mxs_reg_32(hw_apbh_ctrl1)
@ -274,7 +275,7 @@ struct mxs_apbh_regs {
#define APBH_CTRL0_CLKGATE_CHANNEL_NAND7 0x0800
#define APBH_CTRL0_CLKGATE_CHANNEL_HSADC 0x1000
#define APBH_CTRL0_CLKGATE_CHANNEL_LCDIF 0x2000
#elif (defined(CONFIG_MX6) || defined(CONFIG_MX7))
#elif (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M))
#define APBH_CTRL0_CLKGATE_CHANNEL_OFFSET 0
#define APBH_CTRL0_CLKGATE_CHANNEL_NAND0 0x0001
#define APBH_CTRL0_CLKGATE_CHANNEL_NAND1 0x0002
@ -357,7 +358,6 @@ struct mxs_apbh_regs {
#if defined(CONFIG_MX28)
#define APBH_CHANNEL_CTRL_RESET_CHANNEL_MASK (0xffff << 16)
#define APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET 16
#define APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP0 (0x0001 << 16)
#define APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP1 (0x0002 << 16)
#define APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP2 (0x0004 << 16)
@ -390,9 +390,8 @@ struct mxs_apbh_regs {
#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_LCDIF 0x2000
#endif
#if (defined(CONFIG_MX6) || defined(CONFIG_MX7))
/* Not on i.MX23 */
#define APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET 16
#endif
#if defined(CONFIG_MX23)
#define APBH_DEVSEL_CH7_MASK (0xf << 28)

View file

@ -6,7 +6,9 @@
* on behalf of DENX Software Engineering GmbH
*
* Based on code from LTIB:
* Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008-2010, 2016 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2020 NXP
*
*/
#ifndef __MX28_REGS_BCH_H__
@ -40,6 +42,7 @@ struct mxs_bch_regs {
mxs_reg_32(hw_bch_dbgahbmread)
mxs_reg_32(hw_bch_blockname)
mxs_reg_32(hw_bch_version)
mxs_reg_32(hw_bch_debug1)
};
#endif
@ -75,6 +78,9 @@ struct mxs_bch_regs {
#define BCH_MODE_ERASE_THRESHOLD_MASK 0xff
#define BCH_MODE_ERASE_THRESHOLD_OFFSET 0
#define BCH_MODE_ERASE_THRESHOLD(v) \
(((v) << BCH_MODE_ERASE_THRESHOLD_OFFSET) & \
BCH_MODE_ERASE_THRESHOLD_MASK)
#define BCH_ENCODEPTR_ADDR_MASK 0xffffffff
#define BCH_ENCODEPTR_ADDR_OFFSET 0
@ -122,7 +128,7 @@ struct mxs_bch_regs {
#define BCH_FLASHLAYOUT0_NBLOCKS_OFFSET 24
#define BCH_FLASHLAYOUT0_META_SIZE_MASK (0xff << 16)
#define BCH_FLASHLAYOUT0_META_SIZE_OFFSET 16
#if (defined(CONFIG_MX6) || defined(CONFIG_MX7))
#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M))
#define BCH_FLASHLAYOUT0_ECC0_MASK (0x1f << 11)
#define BCH_FLASHLAYOUT0_ECC0_OFFSET 11
#else
@ -146,14 +152,14 @@ struct mxs_bch_regs {
#define BCH_FLASHLAYOUT0_ECC0_ECC28 (0xe << 12)
#define BCH_FLASHLAYOUT0_ECC0_ECC30 (0xf << 12)
#define BCH_FLASHLAYOUT0_ECC0_ECC32 (0x10 << 12)
#define BCH_FLASHLAYOUT0_GF13_0_GF14_1 (1 << 10)
#define BCH_FLASHLAYOUT0_GF13_0_GF14_1_MASK BIT(10)
#define BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET 10
#define BCH_FLASHLAYOUT0_DATA0_SIZE_MASK 0xfff
#define BCH_FLASHLAYOUT0_DATA0_SIZE_MASK 0x3ff
#define BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET 0
#define BCH_FLASHLAYOUT1_PAGE_SIZE_MASK (0xffff << 16)
#define BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET 16
#if (defined(CONFIG_MX6) || defined(CONFIG_MX7))
#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M))
#define BCH_FLASHLAYOUT1_ECCN_MASK (0x1f << 11)
#define BCH_FLASHLAYOUT1_ECCN_OFFSET 11
#else
@ -177,9 +183,9 @@ struct mxs_bch_regs {
#define BCH_FLASHLAYOUT1_ECCN_ECC28 (0xe << 12)
#define BCH_FLASHLAYOUT1_ECCN_ECC30 (0xf << 12)
#define BCH_FLASHLAYOUT1_ECCN_ECC32 (0x10 << 12)
#define BCH_FLASHLAYOUT1_GF13_0_GF14_1 (1 << 10)
#define BCH_FLASHLAYOUT1_GF13_0_GF14_1_MASK BIT(10)
#define BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET 10
#define BCH_FLASHLAYOUT1_DATAN_SIZE_MASK 0xfff
#define BCH_FLASHLAYOUT1_DATAN_SIZE_MASK 0x3ff
#define BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET 0
#define BCH_DEBUG0_RSVD1_MASK (0x1f << 27)

View file

@ -9,6 +9,7 @@
#include <asm/io.h>
#include <asm/mach-imx/regs-common.h>
#include <asm/mach-imx/module_fuse.h>
#include <common.h>
#include "../arch-imx/cpu.h"
@ -197,4 +198,6 @@ unsigned long call_imx_sip(unsigned long id, unsigned long reg0,
unsigned long call_imx_sip_ret2(unsigned long id, unsigned long reg0,
unsigned long *reg1, unsigned long reg2,
unsigned long reg3);
void imx_get_mac_from_fuse(int dev_id, unsigned char *mac);
#endif

View file

@ -27,6 +27,13 @@ config IMX_BOOTAUX
help
bootaux [addr] to boot auxiliary core.
config IMX_MODULE_FUSE
bool "i.MX Module Fuse"
depends on ARCH_MX6
help
i.MX module fuse to runtime disable some driver, including
Linux OS device node.
config USE_IMXIMG_PLUGIN
bool "Use imximage plugin code"
depends on ARCH_MX7 || ARCH_MX6 || ARCH_MX7ULP
@ -82,7 +89,7 @@ config CMD_NANDBCB
bool "i.MX6 NAND Boot Control Block(BCB) command"
depends on MTD_RAW_NAND && CMD_MTDPARTS
select BCH if MX6UL || MX6ULL
default y if (ARCH_MX6 && NAND_MXS) || (ARCH_MX7 && NAND_MXS)
default y if ((ARCH_MX6 || ARCH_MX7 || ARCH_IMX8M) && NAND_MXS)
help
Unlike normal 'nand write/erase' commands, this command update
Boot Control Block(BCB) for i.MX6 platform NAND IP's.

File diff suppressed because it is too large Load diff

View file

@ -168,7 +168,7 @@ int print_cpuinfo(void)
cpurev = get_cpu_rev();
#if defined(CONFIG_IMX_THERMAL)
#if defined(CONFIG_IMX_THERMAL) || defined(CONFIG_IMX_TMU)
struct udevice *thermal_dev;
int cpu_tmp, minc, maxc, ret;
@ -191,7 +191,7 @@ int print_cpuinfo(void)
mxc_get_clock(MXC_ARM_CLK) / 1000000);
#endif
#if defined(CONFIG_IMX_THERMAL)
#if defined(CONFIG_IMX_THERMAL) || defined(CONFIG_IMX_TMU)
puts("CPU: ");
switch (get_cpu_temp_grade(&minc, &maxc)) {
case TEMP_AUTOMOTIVE:

View file

@ -18,11 +18,13 @@ config MU_BASE_SPL
config IMX8QM
select IMX8
select SUPPORT_SPL
select SPL_RECOVER_DATA_SECTION
bool
config IMX8QXP
select IMX8
select SUPPORT_SPL
select SPL_RECOVER_DATA_SECTION
bool
config SYS_SOC
@ -41,6 +43,14 @@ config IMX_CONTAINER_CFG
This is to specific the cfg file for generating container
image which will be loaded by SPL.
config BOOTAUX_RESERVED_MEM_BASE
hex "i.MX auxiliary core dram memory base"
default 0
config BOOTAUX_RESERVED_MEM_SIZE
hex "i.MX auxiliary core dram memory size"
default 0
choice
prompt "i.MX8 board select"
optional

View file

@ -13,13 +13,16 @@
#include <dm/lists.h>
#include <dm/uclass.h>
#include <errno.h>
#include <spl.h>
#include <thermal.h>
#include <asm/arch/sci/sci.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch-imx/cpu.h>
#include <asm/armv8/cpu.h>
#include <asm/armv8/mmu.h>
#include <asm/setup.h>
#include <asm/mach-imx/boot_mode.h>
#include <spl.h>
DECLARE_GLOBAL_DATA_PTR;
@ -38,6 +41,10 @@ struct pass_over_info_t *get_pass_over_info(void)
int arch_cpu_init(void)
{
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RECOVER_DATA_SECTION)
spl_save_restore_data();
#endif
#ifdef CONFIG_SPL_BUILD
struct pass_over_info_t *pass_over;
@ -162,6 +169,37 @@ enum boot_device get_boot_device(void)
return boot_dev;
}
#ifdef CONFIG_SERIAL_TAG
#define FUSE_UNIQUE_ID_WORD0 16
#define FUSE_UNIQUE_ID_WORD1 17
void get_board_serial(struct tag_serialnr *serialnr)
{
sc_err_t err;
u32 val1 = 0, val2 = 0;
u32 word1, word2;
if (!serialnr)
return;
word1 = FUSE_UNIQUE_ID_WORD0;
word2 = FUSE_UNIQUE_ID_WORD1;
err = sc_misc_otp_fuse_read(-1, word1, &val1);
if (err != SC_ERR_NONE) {
printf("%s fuse %d read error: %d\n", __func__, word1, err);
return;
}
err = sc_misc_otp_fuse_read(-1, word2, &val2);
if (err != SC_ERR_NONE) {
printf("%s fuse %d read error: %d\n", __func__, word2, err);
return;
}
serialnr->low = val1;
serialnr->high = val2;
}
#endif /*CONFIG_SERIAL_TAG*/
#ifdef CONFIG_ENV_IS_IN_MMC
__weak int board_mmc_get_env_dev(int devno)
{
@ -223,7 +261,7 @@ static int get_owned_memreg(sc_rm_mr_t mr, sc_faddr_t *addr_start,
phys_size_t get_effective_memsize(void)
{
sc_rm_mr_t mr;
sc_faddr_t start, end, end1;
sc_faddr_t start, end, end1, start_aligned;
int err;
end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
@ -231,9 +269,9 @@ phys_size_t get_effective_memsize(void)
for (mr = 0; mr < 64; mr++) {
err = get_owned_memreg(mr, &start, &end);
if (!err) {
start = roundup(start, MEMSTART_ALIGNMENT);
start_aligned = roundup(start, MEMSTART_ALIGNMENT);
/* Too small memory region, not use it */
if (start > end)
if (start_aligned > end)
continue;
/* Find the memory region runs the U-Boot */
@ -537,3 +575,43 @@ u32 get_cpu_rev(void)
return (id << 12) | rev;
}
void board_boot_order(u32 *spl_boot_list)
{
spl_boot_list[0] = spl_boot_device();
if (spl_boot_list[0] == BOOT_DEVICE_SPI) {
/* Check whether we own the flexspi0, if not, use NOR boot */
if (!sc_rm_is_resource_owned(-1, SC_R_FSPI_0))
spl_boot_list[0] = BOOT_DEVICE_NOR;
}
}
bool m4_parts_booted(void)
{
sc_rm_pt_t m4_parts[2];
int err;
err = sc_rm_get_resource_owner(-1, SC_R_M4_0_PID0, &m4_parts[0]);
if (err) {
printf("%s get resource [%d] owner error: %d\n", __func__,
SC_R_M4_0_PID0, err);
return false;
}
if (sc_pm_is_partition_started(-1, m4_parts[0]))
return true;
if (is_imx8qm()) {
err = sc_rm_get_resource_owner(-1, SC_R_M4_1_PID0, &m4_parts[1]);
if (err) {
printf("%s get resource [%d] owner error: %d\n",
__func__, SC_R_M4_1_PID0, err);
return false;
}
if (sc_pm_is_partition_started(-1, m4_parts[1]))
return true;
}
return false;
}

View file

@ -8,6 +8,7 @@
#include <asm/arch/sys_proto.h>
#include <dm/ofnode.h>
#include <fdt_support.h>
#include <linux/libfdt.h>
DECLARE_GLOBAL_DATA_PTR;
@ -105,13 +106,13 @@ static int config_smmu_resource_sid(int rsrc, int sid)
{
int err;
if (!check_owned_resource(rsrc)) {
printf("%s rsrc[%d] not owned\n", __func__, rsrc);
return -1;
}
err = sc_rm_set_master_sid(-1, rsrc, sid);
debug("set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err);
if (err != SC_ERR_NONE) {
if (!check_owned_resource(rsrc)) {
printf("%s rsrc[%d] not owned\n", __func__, rsrc);
return -1;
}
pr_err("fail set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err);
return -EINVAL;
}
@ -279,6 +280,15 @@ static int ft_add_optee_node(void *fdt, bd_t *bd)
int ft_system_setup(void *blob, bd_t *bd)
{
int ret;
int off;
if (CONFIG_BOOTAUX_RESERVED_MEM_BASE) {
off = fdt_add_mem_rsv(blob, CONFIG_BOOTAUX_RESERVED_MEM_BASE,
CONFIG_BOOTAUX_RESERVED_MEM_SIZE);
if (off < 0)
printf("Failed to reserve memory for bootaux: %s\n",
fdt_strerror(off));
}
update_fdt_with_owned_resources(blob);

View file

@ -55,12 +55,23 @@ config TARGET_IMX8MP_EVK
select SUPPORT_SPL
select IMX8M_LPDDR4
config TARGET_PICO_IMX8MQ
bool "Support Technexion Pico iMX8MQ"
select IMX8MQ
select IMX8M_LPDDR4
config TARGET_VERDIN_IMX8MM
bool "Support Toradex Verdin iMX8M Mini module"
select IMX8MM
select SUPPORT_SPL
select IMX8M_LPDDR4
config TARGET_IMX8MM_BEACON
bool "imx8mm Beacon Embedded devkit"
select IMX8MM
select SUPPORT_SPL
select IMX8M_LPDDR4
endchoice
source "board/freescale/imx8mq_evk/Kconfig"
@ -68,6 +79,8 @@ source "board/freescale/imx8mm_evk/Kconfig"
source "board/freescale/imx8mn_evk/Kconfig"
source "board/freescale/imx8mp_evk/Kconfig"
source "board/google/imx8mq_phanbell/Kconfig"
source "board/technexion/pico-imx8mq/Kconfig"
source "board/toradex/verdin-imx8mm/Kconfig"
source "board/beacon/imx8mm/Kconfig"
endif

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2017 NXP
* Copyright 2017-2019 NXP
*
* Peng Fan <peng.fan@nxp.com>
*/
@ -448,3 +448,76 @@ int arch_misc_init(void)
return 0;
}
#endif
void imx_tmu_arch_init(void *reg_base)
{
if (is_imx8mm() || is_imx8mn()) {
/* Load TCALIV and TASR from fuses */
struct ocotp_regs *ocotp =
(struct ocotp_regs *)OCOTP_BASE_ADDR;
struct fuse_bank *bank = &ocotp->bank[3];
struct fuse_bank3_regs *fuse =
(struct fuse_bank3_regs *)bank->fuse_regs;
u32 tca_rt, tca_hr, tca_en;
u32 buf_vref, buf_slope;
tca_rt = fuse->ana0 & 0xFF;
tca_hr = (fuse->ana0 & 0xFF00) >> 8;
tca_en = (fuse->ana0 & 0x2000000) >> 25;
buf_vref = (fuse->ana0 & 0x1F00000) >> 20;
buf_slope = (fuse->ana0 & 0xF0000) >> 16;
writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
writel((tca_en << 31) | (tca_hr << 16) | tca_rt,
(ulong)reg_base + 0x30);
}
#ifdef CONFIG_IMX8MP
/* Load TCALIV0/1/m40 and TRIM from fuses */
struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
struct fuse_bank *bank = &ocotp->bank[38];
struct fuse_bank38_regs *fuse =
(struct fuse_bank38_regs *)bank->fuse_regs;
struct fuse_bank *bank2 = &ocotp->bank[39];
struct fuse_bank39_regs *fuse2 =
(struct fuse_bank39_regs *)bank2->fuse_regs;
u32 buf_vref, buf_slope, bjt_cur, vlsb, bgr;
u32 reg;
u32 tca40[2], tca25[2], tca105[2];
/* For blank sample */
if (!fuse->ana_trim2 && !fuse->ana_trim3 &&
!fuse->ana_trim4 && !fuse2->ana_trim5) {
/* Use a default 25C binary codes */
tca25[0] = 1596;
tca25[1] = 1596;
writel(tca25[0], (ulong)reg_base + 0x30);
writel(tca25[1], (ulong)reg_base + 0x34);
return;
}
buf_vref = (fuse->ana_trim2 & 0xc0) >> 6;
buf_slope = (fuse->ana_trim2 & 0xF00) >> 8;
bjt_cur = (fuse->ana_trim2 & 0xF000) >> 12;
bgr = (fuse->ana_trim2 & 0xF0000) >> 16;
vlsb = (fuse->ana_trim2 & 0xF00000) >> 20;
writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
reg = (bgr << 28) | (bjt_cur << 20) | (vlsb << 12) | (1 << 7);
writel(reg, (ulong)reg_base + 0x3c);
tca40[0] = (fuse->ana_trim3 & 0xFFF0000) >> 16;
tca25[0] = (fuse->ana_trim3 & 0xF0000000) >> 28;
tca25[0] |= ((fuse->ana_trim4 & 0xFF) << 4);
tca105[0] = (fuse->ana_trim4 & 0xFFF00) >> 8;
tca40[1] = (fuse->ana_trim4 & 0xFFF00000) >> 20;
tca25[1] = fuse2->ana_trim5 & 0xFFF;
tca105[1] = (fuse2->ana_trim5 & 0xFFF000) >> 12;
/* use 25c for 1p calibration */
writel(tca25[0] | (tca105[0] << 16), (ulong)reg_base + 0x30);
writel(tca25[1] | (tca105[1] << 16), (ulong)reg_base + 0x34);
writel(tca40[0] | (tca40[1] << 16), (ulong)reg_base + 0x38);
#endif
}

View file

@ -6,6 +6,7 @@
# (C) Copyright 2011 Freescale Semiconductor, Inc.
obj-y := soc.o clock.o
obj-$(CONFIG_IMX_MODULE_FUSE) += module_fuse.o
obj-$(CONFIG_SPL_BUILD) += ddr.o
obj-$(CONFIG_MP) += mp.o
obj-$(CONFIG_MX6UL_LITESOM) += litesom.o

View file

@ -0,0 +1,322 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 NXP
*/
#include <common.h>
#include <fdt_support.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/imx-regs.h>
#include <asm/mach-imx/module_fuse.h>
#include <linux/errno.h>
static struct fuse_entry_desc mx6_fuse_descs[] = {
#if defined(CONFIG_MX6ULL)
{MODULE_TSC, "/soc/aips-bus@2000000/tsc@2040000", 0x430, 22},
{MODULE_ADC2, "/soc/aips-bus@2100000/adc@219c000", 0x430, 23},
{MODULE_EPDC, "/soc/aips-bus@2200000/epdc@228c000", 0x430, 24},
{MODULE_ESAI, "/soc/aips-bus@2000000/spba-bus@2000000/esai@2024000", 0x430, 25},
{MODULE_FLEXCAN1, "/soc/aips-bus@2000000/can@2090000", 0x430, 26},
{MODULE_FLEXCAN2, "/soc/aips-bus@2000000/can@2094000", 0x430, 27},
{MODULE_SPDIF, "/soc/aips-bus@2000000/spba-bus@2000000/spdif@2004000", 0x440, 2},
{MODULE_EIM, "/soc/aips-bus@2100000/weim@21b8000", 0x440, 3},
{MODULE_SD1, "/soc/aips-bus@2100000/usdhc@2190000", 0x440, 4},
{MODULE_SD2, "/soc/aips-bus@2100000/usdhc@2194000", 0x440, 5},
{MODULE_QSPI1, "/soc/aips-bus@2100000/qspi@21e0000", 0x440, 6},
{MODULE_GPMI, "/soc/gpmi-nand@1806000", 0x440, 7},
{MODULE_APBHDMA, "/soc/dma-apbh@1804000", 0x440, 7},
{MODULE_LCDIF, "/soc/aips-bus@2100000/lcdif@21c8000", 0x440, 8},
{MODULE_PXP, "/soc/aips-bus@2100000/pxp@21cc000", 0x440, 9},
{MODULE_CSI, "/soc/aips-bus@2100000/csi@21c4000", 0x440, 10},
{MODULE_ADC1, "/soc/aips-bus@2100000/adc@2198000", 0x440, 11},
{MODULE_ENET1, "/soc/aips-bus@2100000/ethernet@2188000", 0x440, 12},
{MODULE_ENET2, "/soc/aips-bus@2000000/ethernet@20b4000", 0x440, 13},
{MODULE_DCP, "/soc/aips-bus@2200000/dcp@2280000", 0x440, 14},
{MODULE_USB_OTG2, "/soc/aips-bus@2100000/usb@2184200", 0x440, 15},
{MODULE_SAI2, "/soc/aips-bus@2000000/spba-bus@2000000/sai@202c000", 0x440, 24},
{MODULE_SAI3, "/soc/aips-bus@2000000/spba-bus@2000000/sai@2030000", 0x440, 24},
{MODULE_DCP_CRYPTO, "/soc/aips-bus@2200000/dcp@2280000", 0x440, 25},
{MODULE_UART5, "/soc/aips-bus@2100000/serial@21f4000", 0x440, 26},
{MODULE_UART6, "/soc/aips-bus@2100000/serial@21fc000", 0x440, 26},
{MODULE_UART7, "/soc/aips-bus@2000000/spba-bus@2000000/serial@2018000", 0x440, 26},
{MODULE_UART8, "/soc/aips-bus@2200000/serial@2288000", 0x440, 26},
{MODULE_PWM5, "/soc/aips-bus@2000000/pwm@20f0000", 0x440, 27},
{MODULE_PWM6, "/soc/aips-bus@2000000/pwm@20f4000", 0x440, 27},
{MODULE_PWM7, "/soc/aips-bus@2000000/pwm@20f8000", 0x440, 27},
{MODULE_PWM8, "/soc/aips-bus@2000000/pwm@20fc000", 0x440, 27},
{MODULE_ECSPI3, "/soc/aips-bus@2000000/spba-bus@2000000/ecspi@2010000", 0x440, 28},
{MODULE_ECSPI4, "/soc/aips-bus@2000000/spba-bus@2000000/ecspi@2014000", 0x440, 28},
{MODULE_I2C3, "/soc/aips-bus@2100000/i2c@21a8000", 0x440, 29},
{MODULE_I2C4, "/soc/aips-bus@2100000/i2c@21f8000", 0x440, 29},
{MODULE_GPT2, "/soc/aips-bus@2000000/gpt@20e8000", 0x440, 30},
{MODULE_EPIT2, "/soc/aips-bus@2000000/epit@20d4000", 0x440, 31},
/* Paths for older imx tree: */
{MODULE_TSC, "/soc/aips-bus@02000000/tsc@02040000", 0x430, 22},
{MODULE_ADC2, "/soc/aips-bus@02100000/adc@0219c000", 0x430, 23},
{MODULE_EPDC, "/soc/aips-bus@02200000/epdc@0228c000", 0x430, 24},
{MODULE_ESAI, "/soc/aips-bus@02000000/spba-bus@02000000/esai@02024000", 0x430, 25},
{MODULE_FLEXCAN1, "/soc/aips-bus@02000000/can@02090000", 0x430, 26},
{MODULE_FLEXCAN2, "/soc/aips-bus@02000000/can@02094000", 0x430, 27},
{MODULE_SPDIF, "/soc/aips-bus@02000000/spba-bus@02000000/spdif@02004000", 0x440, 2},
{MODULE_EIM, "/soc/aips-bus@02100000/weim@021b8000", 0x440, 3},
{MODULE_SD1, "/soc/aips-bus@02100000/usdhc@02190000", 0x440, 4},
{MODULE_SD2, "/soc/aips-bus@02100000/usdhc@02194000", 0x440, 5},
{MODULE_QSPI1, "/soc/aips-bus@02100000/qspi@021e0000", 0x440, 6},
{MODULE_GPMI, "/soc/gpmi-nand@01806000", 0x440, 7},
{MODULE_APBHDMA, "/soc/dma-apbh@01804000", 0x440, 7},
{MODULE_LCDIF, "/soc/aips-bus@02100000/lcdif@021c8000", 0x440, 8},
{MODULE_PXP, "/soc/aips-bus@02100000/pxp@021cc000", 0x440, 9},
{MODULE_CSI, "/soc/aips-bus@02100000/csi@021c4000", 0x440, 10},
{MODULE_ADC1, "/soc/aips-bus@02100000/adc@02198000", 0x440, 11},
{MODULE_ENET1, "/soc/aips-bus@02100000/ethernet@02188000", 0x440, 12},
{MODULE_ENET2, "/soc/aips-bus@02000000/ethernet@020b4000", 0x440, 13},
{MODULE_DCP, "/soc/aips-bus@02200000/dcp@02280000", 0x440, 14},
{MODULE_USB_OTG2, "/soc/aips-bus@02100000/usb@02184200", 0x440, 15},
{MODULE_SAI2, "/soc/aips-bus@02000000/spba-bus@02000000/sai@0202c000", 0x440, 24},
{MODULE_SAI3, "/soc/aips-bus@02000000/spba-bus@02000000/sai@02030000", 0x440, 24},
{MODULE_DCP_CRYPTO, "/soc/aips-bus@02200000/dcp@02280000", 0x440, 25},
{MODULE_UART5, "/soc/aips-bus@02100000/serial@021f4000", 0x440, 26},
{MODULE_UART6, "/soc/aips-bus@02100000/serial@021fc000", 0x440, 26},
{MODULE_UART7, "/soc/aips-bus@02000000/spba-bus@02000000/serial@02018000", 0x440, 26},
{MODULE_UART8, "/soc/aips-bus@02200000/serial@02288000", 0x440, 26},
{MODULE_PWM5, "/soc/aips-bus@02000000/pwm@020f0000", 0x440, 27},
{MODULE_PWM6, "/soc/aips-bus@02000000/pwm@020f4000", 0x440, 27},
{MODULE_PWM7, "/soc/aips-bus@02000000/pwm@020f8000", 0x440, 27},
{MODULE_PWM8, "/soc/aips-bus@02000000/pwm@020fc000", 0x440, 27},
{MODULE_ECSPI3, "/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02010000", 0x440, 28},
{MODULE_ECSPI4, "/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02014000", 0x440, 28},
{MODULE_I2C3, "/soc/aips-bus@02100000/i2c@021a8000", 0x440, 29},
{MODULE_I2C4, "/soc/aips-bus@02100000/i2c@021f8000", 0x440, 29},
{MODULE_GPT2, "/soc/aips-bus@02000000/gpt@020e8000", 0x440, 30},
{MODULE_EPIT2, "/soc/aips-bus@02000000/epit@020d4000", 0x440, 31},
#elif defined(CONFIG_MX6UL)
{MODULE_TSC, "/soc/aips-bus@2000000/tsc@2040000", 0x430, 22},
{MODULE_ADC2, "/soc/aips-bus@2100000/adc@219c000", 0x430, 23},
{MODULE_SIM1, "/soc/aips-bus@2100000/sim@218c000", 0x430, 24},
{MODULE_SIM2, "/soc/aips-bus@2100000/sim@21b4000", 0x430, 25},
{MODULE_FLEXCAN1, "/soc/aips-bus@2000000/can@2090000", 0x430, 26},
{MODULE_FLEXCAN2, "/soc/aips-bus@2000000/can@2094000", 0x430, 27},
{MODULE_SPDIF, "/soc/aips-bus@2000000/spba-bus@2000000/spdif@2004000", 0x440, 2},
{MODULE_EIM, "/soc/aips-bus@2100000/weim@21b8000", 0x440, 3},
{MODULE_SD1, "/soc/aips-bus@2100000/usdhc@2190000", 0x440, 4},
{MODULE_SD2, "/soc/aips-bus@2100000/usdhc@2194000", 0x440, 5},
{MODULE_QSPI1, "/soc/aips-bus@2100000/qspi@21e0000", 0x440, 6},
{MODULE_GPMI, "/soc/gpmi-nand@1806000", 0x440, 7},
{MODULE_APBHDMA, "/soc/dma-apbh@1804000", 0x440, 7},
{MODULE_LCDIF, "/soc/aips-bus@2100000/lcdif@21c8000", 0x440, 8},
{MODULE_PXP, "/soc/aips-bus@2100000/pxp@21cc000", 0x440, 9},
{MODULE_CSI, "/soc/aips-bus@2100000/csi@21c4000", 0x440, 10},
{MODULE_ADC1, "/soc/aips-bus@2100000/adc@2198000", 0x440, 11},
{MODULE_ENET1, "/soc/aips-bus@2100000/ethernet@2188000", 0x440, 12},
{MODULE_ENET2, "/soc/aips-bus@2000000/ethernet@20b4000", 0x440, 13},
{MODULE_CAAM, "/soc/aips-bus@2100000/caam@2140000", 0x440, 14},
{MODULE_USB_OTG2, "/soc/aips-bus@2100000/usb@2184200", 0x440, 15},
{MODULE_SAI2, "/soc/aips-bus@2000000/spba-bus@2000000/sai@202c000", 0x440, 24},
{MODULE_SAI3, "/soc/aips-bus@2000000/spba-bus@2000000/sai@2030000", 0x440, 24},
{MODULE_BEE, "/soc/aips-bus@2000000/bee@2044000", 0x440, 25},
{MODULE_UART5, "/soc/aips-bus@2100000/serial@21f4000", 0x440, 26},
{MODULE_UART6, "/soc/aips-bus@2100000/serial@21fc000", 0x440, 26},
{MODULE_UART7, "/soc/aips-bus@2000000/spba-bus@2000000/serial@2018000", 0x440, 26},
{MODULE_UART8, "/soc/aips-bus@2000000/spba-bus@2000000/serial@2024000", 0x440, 26},
{MODULE_PWM5, "/soc/aips-bus@2000000/pwm@20f0000", 0x440, 27},
{MODULE_PWM6, "/soc/aips-bus@2000000/pwm@20f4000", 0x440, 27},
{MODULE_PWM7, "/soc/aips-bus@2000000/pwm@20f8000", 0x440, 27},
{MODULE_PWM8, "/soc/aips-bus@2000000/pwm@20fc000", 0x440, 27},
{MODULE_ECSPI3, "/soc/aips-bus@2000000/spba-bus@2000000/ecspi@2010000", 0x440, 28},
{MODULE_ECSPI4, "/soc/aips-bus@2000000/spba-bus@2000000/ecspi@2014000", 0x440, 28},
{MODULE_I2C3, "/soc/aips-bus@2100000/i2c@21a8000", 0x440, 29},
{MODULE_I2C4, "/soc/aips-bus@2100000/i2c@21f8000", 0x440, 29},
{MODULE_GPT2, "/soc/aips-bus@2000000/gpt@20e8000", 0x440, 30},
{MODULE_EPIT2, "/soc/aips-bus@2000000/epit@20d4000", 0x440, 31},
/* Paths for older imx tree: */
{MODULE_TSC, "/soc/aips-bus@02000000/tsc@02040000", 0x430, 22},
{MODULE_ADC2, "/soc/aips-bus@02100000/adc@0219c000", 0x430, 23},
{MODULE_SIM1, "/soc/aips-bus@02100000/sim@0218c000", 0x430, 24},
{MODULE_SIM2, "/soc/aips-bus@02100000/sim@021b4000", 0x430, 25},
{MODULE_FLEXCAN1, "/soc/aips-bus@02000000/can@02090000", 0x430, 26},
{MODULE_FLEXCAN2, "/soc/aips-bus@02000000/can@02094000", 0x430, 27},
{MODULE_SPDIF, "/soc/aips-bus@02000000/spba-bus@02000000/spdif@02004000", 0x440, 2},
{MODULE_EIM, "/soc/aips-bus@02100000/weim@021b8000", 0x440, 3},
{MODULE_SD1, "/soc/aips-bus@02100000/usdhc@02190000", 0x440, 4},
{MODULE_SD2, "/soc/aips-bus@02100000/usdhc@02194000", 0x440, 5},
{MODULE_QSPI1, "/soc/aips-bus@02100000/qspi@021e0000", 0x440, 6},
{MODULE_GPMI, "/soc/gpmi-nand@01806000", 0x440, 7},
{MODULE_APBHDMA, "/soc/dma-apbh@01804000", 0x440, 7},
{MODULE_LCDIF, "/soc/aips-bus@02100000/lcdif@021c8000", 0x440, 8},
{MODULE_PXP, "/soc/aips-bus@02100000/pxp@021cc000", 0x440, 9},
{MODULE_CSI, "/soc/aips-bus@02100000/csi@021c4000", 0x440, 10},
{MODULE_ADC1, "/soc/aips-bus@02100000/adc@02198000", 0x440, 11},
{MODULE_ENET1, "/soc/aips-bus@02100000/ethernet@02188000", 0x440, 12},
{MODULE_ENET2, "/soc/aips-bus@02000000/ethernet@020b4000", 0x440, 13},
{MODULE_CAAM, "/soc/aips-bus@02100000/caam@2140000", 0x440, 14},
{MODULE_USB_OTG2, "/soc/aips-bus@02100000/usb@02184200", 0x440, 15},
{MODULE_SAI2, "/soc/aips-bus@02000000/spba-bus@02000000/sai@0202c000", 0x440, 24},
{MODULE_SAI3, "/soc/aips-bus@02000000/spba-bus@02000000/sai@02030000", 0x440, 24},
{MODULE_BEE, "/soc/aips-bus@02000000/bee@02044000", 0x440, 25},
{MODULE_UART5, "/soc/aips-bus@02100000/serial@021f4000", 0x440, 26},
{MODULE_UART6, "/soc/aips-bus@02100000/serial@021fc000", 0x440, 26},
{MODULE_UART7, "/soc/aips-bus@02000000/spba-bus@02000000/serial@02018000", 0x440, 26},
{MODULE_UART8, "/soc/aips-bus@02000000/spba-bus@02000000/serial@02024000", 0x440, 26},
{MODULE_PWM5, "/soc/aips-bus@02000000/pwm@020f0000", 0x440, 27},
{MODULE_PWM6, "/soc/aips-bus@02000000/pwm@020f4000", 0x440, 27},
{MODULE_PWM7, "/soc/aips-bus@02000000/pwm@020f8000", 0x440, 27},
{MODULE_PWM8, "/soc/aips-bus@02000000/pwm@020fc000", 0x440, 27},
{MODULE_ECSPI3, "/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02010000", 0x440, 28},
{MODULE_ECSPI4, "/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02014000", 0x440, 28},
{MODULE_I2C3, "/soc/aips-bus@02100000/i2c@021a8000", 0x440, 29},
{MODULE_I2C4, "/soc/aips-bus@02100000/i2c@021f8000", 0x440, 29},
{MODULE_GPT2, "/soc/aips-bus@02000000/gpt@020e8000", 0x440, 30},
{MODULE_EPIT2, "/soc/aips-bus@02000000/epit@020d4000", 0x440, 31},
#endif
};
u32 check_module_fused(enum fuse_module_type module)
{
u32 i, reg;
for (i = 0; i < ARRAY_SIZE(mx6_fuse_descs); i++) {
if (mx6_fuse_descs[i].module == module) {
reg = readl(OCOTP_BASE_ADDR +
mx6_fuse_descs[i].fuse_word_offset);
if (reg & BIT(mx6_fuse_descs[i].fuse_bit_offset))
return 1; /* disabled */
else
return 0; /* enabled */
}
}
return 0; /* Not has a fuse, always enabled */
}
#ifdef CONFIG_OF_SYSTEM_SETUP
int ft_system_setup(void *blob, bd_t *bd)
{
const char *status = "disabled";
u32 i, reg;
int rc, off;
for (i = 0; i < ARRAY_SIZE(mx6_fuse_descs); i++) {
reg = readl(OCOTP_BASE_ADDR +
mx6_fuse_descs[i].fuse_word_offset);
if (reg & BIT(mx6_fuse_descs[i].fuse_bit_offset)) {
off = fdt_path_offset(blob,
mx6_fuse_descs[i].node_path);
if (off < 0)
continue; /* Not found, skip it */
add_status:
rc = fdt_setprop(blob, nodeoff, "status", status,
strlen(status) + 1);
if (rc) {
if (rc == -FDT_ERR_NOSPACE) {
rc = fdt_increase_size(blob, 512);
if (!rc)
goto add_status;
}
printf("Unable to update property %s:%s, err=%s\n", mx6_fuse_descs[i].node_path, "status", fdt_strerror(rc));
} else {
printf("Modify %s disabled\n", mx6_fuse_descs[i].node_path);
}
}
}
return 0;
}
#endif
u32 esdhc_fused(ulong base_addr)
{
switch (base_addr) {
case USDHC1_BASE_ADDR:
return check_module_fused(MODULE_SD1);
case USDHC2_BASE_ADDR:
return check_module_fused(MODULE_SD2);
#ifdef USDHC3_BASE_ADDR
case USDHC3_BASE_ADDR:
return check_module_fused(MODULE_SD3);
#endif
#ifdef USDHC4_BASE_ADDR
case USDHC4_BASE_ADDR:
return check_module_fused(MODULE_SD4);
#endif
default:
return 0;
}
}
u32 ecspi_fused(ulong base_addr)
{
switch (base_addr) {
case ECSPI1_BASE_ADDR:
return check_module_fused(MODULE_ECSPI1);
case ECSPI2_BASE_ADDR:
return check_module_fused(MODULE_ECSPI2);
case ECSPI3_BASE_ADDR:
return check_module_fused(MODULE_ECSPI3);
case ECSPI4_BASE_ADDR:
return check_module_fused(MODULE_ECSPI4);
#ifdef ECSPI5_BASE_ADDR
case ECSPI5_BASE_ADDR:
return check_module_fused(MODULE_ECSPI5);
#endif
default:
return 0;
}
}
u32 usb_fused(ulong base_addr)
{
int i = (base_addr - USB_BASE_ADDR) / 0x200;
return check_module_fused(MODULE_USB_OTG1 + i);
}
u32 qspi_fused(ulong base_addr)
{
switch (base_addr) {
#ifdef QSPI1_BASE_ADDR
case QSPI1_BASE_ADDR:
return check_module_fused(MODULE_QSPI1);
#endif
#ifdef QSPI2_BASE_ADDR
case QSPI2_BASE_ADDR:
return check_module_fused(MODULE_QSPI2);
#endif
default:
return 0;
}
}
u32 i2c_fused(ulong base_addr)
{
switch (base_addr) {
case I2C1_BASE_ADDR:
return check_module_fused(MODULE_I2C1);
case I2C2_BASE_ADDR:
return check_module_fused(MODULE_I2C2);
case I2C3_BASE_ADDR:
return check_module_fused(MODULE_I2C3);
#ifdef I2C4_BASE_ADDR
case I2C4_BASE_ADDR:
return check_module_fused(MODULE_I2C4);
#endif
}
return 0;
}
u32 enet_fused(ulong base_addr)
{
switch (base_addr) {
case ENET_BASE_ADDR:
return check_module_fused(MODULE_ENET1);
#ifdef ENET2_BASE_ADDR
case ENET2_BASE_ADDR:
return check_module_fused(MODULE_ENET2);
#endif
default:
return 0;
}
}

View file

@ -0,0 +1,14 @@
if TARGET_IMX8MM_BEACON
config SYS_BOARD
default "imx8mm"
config SYS_VENDOR
default "beacon"
config SYS_CONFIG_NAME
default "imx8mm_beacon"
source "board/freescale/common/Kconfig"
endif

View file

@ -0,0 +1,7 @@
i.MX8MM Beacon EmbeddedWorks Devkit
M: Adam Ford <aford173@gmail.com>
S: Maintained
F: board/beacon/imx8mm/
F: include/configs/imx8mm_beacon.h
F: configs/imx8mm_beacon_defconfig

View file

@ -0,0 +1,13 @@
#
# Copyright 2020 Compass Electronics Group, LLC
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += imx8mm_beacon.o
obj-y += ../../freescale/common/
ifdef CONFIG_SPL_BUILD
obj-y += spl.o
obj-y += lpddr4_timing.o
endif

View file

@ -0,0 +1,37 @@
U-Boot for the Beacon EmbeddedWorks Devkit
Quick Start
===========
- Build the ARM Trusted firmware binary
- Get ddr firmware
- Build U-Boot
- Boot
Get and Build the ARM Trusted firmware
======================================
Note: $(srctree) is U-Boot source directory
$ git clone https://source.codeaurora.org/external/imx/imx-atf
$ git checkout imx_4.19.35_1.0.0
$ make PLAT=imx8mm bl31 ARCH=arm CROSS_COMPILE=aarch64-linux-gnu-
$ cp build/imx8mm/release/bl31.bin $(srctree)
Get the DDR firmware
====================
$ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.5.bin
$ chmod +x firmware-imx-8.5.bin
$ ./firmware-imx-8.5
$ cp firmware-imx-8.5/firmware/ddr/synopsys/lpddr4*.bin $(srctree)
Build U-Boot
============
$ make imx8mm_beacon_defconfig
$ make flash.bin ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- ATF_LOAD_ADDR=0x920000
Burn U-Boot to microSD Card
===========================
$ sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=33
Boot
====
Set Boot switch to SD boot

View file

@ -0,0 +1,67 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2020 Compass Electronics Group, LLC
*/
#include <common.h>
#include <miiphy.h>
#include <netdev.h>
#include <asm/arch/clock.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
/* rom_pointer[1] contains the size of TEE occupies */
if (rom_pointer[1])
gd->ram_size = PHYS_SDRAM_SIZE - rom_pointer[1];
else
gd->ram_size = PHYS_SDRAM_SIZE;
return 0;
}
#if IS_ENABLED(CONFIG_FEC_MXC)
static int setup_fec(void)
{
struct iomuxc_gpr_base_regs *gpr =
(struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
/* Use 125M anatop REF_CLK1 for ENET1, not from external */
clrsetbits_le32(&gpr->gpr[1], 0x2000, 0);
return 0;
}
int board_phy_config(struct phy_device *phydev)
{
/* enable rgmii rxc skew and phy mode select to RGMII copper */
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x8);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x00);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x82ee);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
if (phydev->drv->config)
phydev->drv->config(phydev);
return 0;
}
#endif
int board_init(void)
{
if (IS_ENABLED(CONFIG_FEC_MXC))
setup_fec();
return 0;
}
int board_mmc_get_env_dev(int devno)
{
return devno;
}

File diff suppressed because it is too large Load diff

155
board/beacon/imx8mm/spl.c Normal file
View file

@ -0,0 +1,155 @@
// SPDX-License-Identifier: GPL-2.0+
#include <common.h>
#include <cpu_func.h>
#include <hang.h>
#include <spl.h>
#include <asm/io.h>
#include <asm/mach-imx/iomux-v3.h>
#include <asm/arch/clock.h>
#include <asm/arch/imx8mm_pins.h>
#include <asm/arch/sys_proto.h>
#include <asm/mach-imx/boot_mode.h>
#include <asm/arch/ddr.h>
#include <dm/uclass.h>
#include <dm/device.h>
#include <dm/uclass-internal.h>
#include <dm/device-internal.h>
#include <power/pmic.h>
#include <power/bd71837.h>
DECLARE_GLOBAL_DATA_PTR;
int spl_board_boot_device(enum boot_device boot_dev_spl)
{
switch (boot_dev_spl) {
case SD2_BOOT:
case MMC2_BOOT:
return BOOT_DEVICE_MMC1;
case SD3_BOOT:
case MMC3_BOOT:
return BOOT_DEVICE_MMC2;
default:
return BOOT_DEVICE_NONE;
}
}
static void spl_dram_init(void)
{
ddr_init(&dram_timing);
}
void spl_board_init(void)
{
debug("Normal Boot\n");
}
#ifdef CONFIG_SPL_LOAD_FIT
int board_fit_config_name_match(const char *name)
{
/* Just empty function now - can't decide what to choose */
debug("%s: %s\n", __func__, name);
return 0;
}
#endif
#define UART_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_FSEL1)
#define WDOG_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_ODE | PAD_CTL_PUE | PAD_CTL_PE)
static iomux_v3_cfg_t const uart_pads[] = {
IMX8MM_PAD_UART2_RXD_UART2_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
IMX8MM_PAD_UART2_TXD_UART2_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
};
static iomux_v3_cfg_t const wdog_pads[] = {
IMX8MM_PAD_GPIO1_IO02_WDOG1_WDOG_B | MUX_PAD_CTRL(WDOG_PAD_CTRL),
};
int board_early_init_f(void)
{
struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
imx_iomux_v3_setup_multiple_pads(wdog_pads, ARRAY_SIZE(wdog_pads));
set_wdog_reset(wdog);
imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads));
return 0;
}
static int power_init_board(void)
{
struct udevice *dev;
int ret;
ret = pmic_get("pmic@4b", &dev);
if (ret == -ENODEV) {
puts("No pmic\n");
return 0;
}
if (ret != 0)
return ret;
/* decrease RESET key long push time from the default 10s to 10ms */
pmic_reg_write(dev, BD718XX_PWRONCONFIG1, 0x0);
/* unlock the PMIC regs */
pmic_reg_write(dev, BD718XX_REGLOCK, 0x1);
/* increase VDD_SOC to typical value 0.85v before first DRAM access */
pmic_reg_write(dev, BD718XX_BUCK1_VOLT_RUN, 0x0f);
/* increase VDD_DRAM to 0.975v for 3Ghz DDR */
pmic_reg_write(dev, BD718XX_1ST_NODVS_BUCK_VOLT, 0x83);
/* lock the PMIC regs */
pmic_reg_write(dev, BD718XX_REGLOCK, 0x11);
return 0;
}
void board_init_f(ulong dummy)
{
struct udevice *dev;
int ret;
arch_cpu_init();
init_uart_clk(1);
board_early_init_f();
timer_init();
preloader_console_init();
/* Clear the BSS. */
memset(__bss_start, 0, __bss_end - __bss_start);
ret = spl_early_init();
if (ret) {
debug("spl_early_init() failed: %d\n", ret);
hang();
}
ret = uclass_get_device_by_name(UCLASS_CLK,
"clock-controller@30380000",
&dev);
if (ret < 0) {
printf("Failed to find clock node. Check device tree\n");
hang();
}
enable_tzc380();
power_init_board();
/* DDR initialization */
spl_dram_init();
board_init_r(NULL, 0);
}

View file

@ -123,10 +123,23 @@ int board_mmc_get_env_dev(int devno)
int board_late_init(void)
{
char *fdt_file;
bool m4_booted;
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
env_set("board_name", "MEK");
env_set("board_rev", "iMX8QM");
#endif
fdt_file = env_get("fdt_file");
m4_booted = m4_parts_booted();
if (fdt_file && !strcmp(fdt_file, "undefined")) {
if (m4_booted)
env_set("fdt_file", "imx8qm-mek-rpmsg.dtb");
else
env_set("fdt_file", "imx8qm-mek.dtb");
}
return 0;
}

View file

@ -12,6 +12,7 @@
#include <dm/uclass-internal.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
#include <asm/arch/sys_proto.h>
DECLARE_GLOBAL_DATA_PTR;
@ -37,6 +38,11 @@ void spl_board_init(void)
puts("Normal Boot\n");
}
void spl_board_prepare_for_boot(void)
{
imx8_power_off_pd_devices(NULL, 0);
}
#ifdef CONFIG_SPL_LOAD_FIT
int board_fit_config_name_match(const char *name)
{

View file

@ -146,10 +146,23 @@ int board_mmc_get_env_dev(int devno)
int board_late_init(void)
{
char *fdt_file;
bool m4_booted;
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
env_set("board_name", "MEK");
env_set("board_rev", "iMX8QXP");
#endif
fdt_file = env_get("fdt_file");
m4_booted = m4_parts_booted();
if (fdt_file && !strcmp(fdt_file, "undefined")) {
if (m4_booted)
env_set("fdt_file", "imx8qxp-mek-rpmsg.dtb");
else
env_set("fdt_file", "imx8qxp-mek.dtb");
}
return 0;
}

View file

@ -17,6 +17,7 @@
#include <asm/arch/sci/sci.h>
#include <asm/arch/imx8-pins.h>
#include <asm/arch/iomux.h>
#include <asm/arch/sys_proto.h>
DECLARE_GLOBAL_DATA_PTR;
@ -55,6 +56,11 @@ void spl_board_init(void)
puts("Normal Boot\n");
}
void spl_board_prepare_for_boot(void)
{
imx8_power_off_pd_devices(NULL, 0);
}
#ifdef CONFIG_SPL_LOAD_FIT
int board_fit_config_name_match(const char *name)
{

View file

@ -0,0 +1,12 @@
if TARGET_PICO_IMX8MQ
config SYS_BOARD
default "pico-imx8mq"
config SYS_VENDOR
default "technexion"
config SYS_CONFIG_NAME
default "pico-imx8mq"
endif

View file

@ -0,0 +1,6 @@
PICOPI IMX8MQ BOARD
M: Marek Vasut <marek.vasut@gmail.com>
S: Maintained
F: board/technexion/pico-imx8mq/
F: include/configs/pico-imx8mq.h
F: configs/pico-imx8mq_defconfig

View file

@ -0,0 +1,12 @@
#
# Copyright 2017 NXP
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += pico-imx8mq.o
ifdef CONFIG_SPL_BUILD
obj-y += spl.o
obj-$(CONFIG_IMX8M_LPDDR4) += lpddr4_timing_1gb.o lpddr4_timing_2gb.o lpddr4_timing_3gb.o lpddr4_timing_4gb.o
endif

View file

@ -0,0 +1,52 @@
U-Boot for the Technexion Pico i.MX8MQ
Quick Start
===========
- Build the TFA binary
- Get DDR and HDMI firmware
- Build U-Boot
- Boot
Get and Build the TFA blob
==========================
Note: srctree is U-Boot source directory
Get ATF from: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
branch: master
$ CROSS_COMPILE=aarch64-linux-gnu- make PLAT=imx8mq bl31
$ cp build/imx8mq/release/bl31.bin $(builddir)
Get the DDR and HDMI firmware
=============================
$ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-7.9.bin
$ chmod +x firmware-imx-7.9.bin
$ ./firmware-imx-7.9.bin
# Or use this to avoid running random scripts from the internet,
# but note that you must agree to the license the script displays:
# $ dd if=firmware-imx-7.9.bin of=firmware-imx-7.9.tar.bz2 bs=38868 skip=1
# $ tar -xf firmware-imx-7.9.tar.bz2
$ cp firmware-imx-7.9/firmware/hdmi/cadence/signed_hdmi_imx8m.bin $(builddir)
$ cp firmware-imx-7.9/firmware/ddr/synopsys/lpddr4*.bin $(builddir)
Build U-Boot
============
$ export CROSS_COMPILE=aarch64-poky-linux-
$ make pico-imx8mq_defconfig
$ make flash.bin
Burn the flash.bin to MicroSD card offset 33KB
$ dd if=flash.bin of=/dev/mmcblkX bs=1024 seek=33
Or into eMMC from a running system
$ dhcp flash.bin && mmc write $loadaddr 0x42 0x800
Boot
====
"o" denotes a pin
"[]" denotes two pins bridged by a jumper
eMMC boot:
J1 o[] []o J2
[]o o[]
USB upload via USB-C connector:
J1 ooo ooo J2
o[] []o

View file

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2020 Marek Vasut <marek.vasut@gmail.com>
*/
#ifndef __LPDDR4_TIMING_H__
#define __LPDDR4_TIMING_H__
extern struct dram_timing_info dram_timing_1gb;
extern struct dram_timing_info dram_timing_2gb;
extern struct dram_timing_info dram_timing_3gb;
extern struct dram_timing_info dram_timing_4gb;
#endif /* __LPDDR4_TIMING_H__ */

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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,146 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018 NXP
*/
#include <common.h>
#include <env.h>
#include <init.h>
#include <malloc.h>
#include <errno.h>
#include <asm/io.h>
#include <miiphy.h>
#include <netdev.h>
#include <asm/mach-imx/iomux-v3.h>
#include <asm-generic/gpio.h>
#include <fsl_esdhc_imx.h>
#include <mmc.h>
#include <asm/arch/imx8mq_pins.h>
#include <asm/arch/sys_proto.h>
#include <asm/mach-imx/gpio.h>
#include <asm/mach-imx/mxc_i2c.h>
#include <asm/arch/clock.h>
#include <spl.h>
#include <power/pmic.h>
DECLARE_GLOBAL_DATA_PTR;
#define UART_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_FSEL1)
#define WDOG_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE)
static iomux_v3_cfg_t const wdog_pads[] = {
IMX8MQ_PAD_GPIO1_IO02__WDOG1_WDOG_B | MUX_PAD_CTRL(WDOG_PAD_CTRL),
};
static iomux_v3_cfg_t const uart_pads[] = {
IMX8MQ_PAD_UART1_RXD__UART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
IMX8MQ_PAD_UART1_TXD__UART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
};
int board_early_init_f(void)
{
struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
imx_iomux_v3_setup_multiple_pads(wdog_pads, ARRAY_SIZE(wdog_pads));
set_wdog_reset(wdog);
imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads));
return 0;
}
int dram_init(void)
{
int ddr_size = readl(M4_BOOTROM_BASE_ADDR);
if (ddr_size == 0x4)
gd->ram_size = 0x100000000;
else if (ddr_size == 0x3)
gd->ram_size = 0xc0000000;
else if (ddr_size == 0x2)
gd->ram_size = 0x80000000;
else if (ddr_size == 0x1)
gd->ram_size = 0x40000000;
else
printf("Unknown DDR type!!!\n");
/* rom_pointer[1] contains the size of TEE occupies */
if (rom_pointer[1])
gd->ram_size -= rom_pointer[1];
return 0;
}
#ifdef CONFIG_FEC_MXC
#define FEC_RST_PAD IMX_GPIO_NR(1, 9)
#define FEC_PWR_PAD IMX_GPIO_NR(1, 0)
static iomux_v3_cfg_t const fec1_pads[] = {
/* Reset */
IMX8MQ_PAD_GPIO1_IO09__GPIO1_IO9 | MUX_PAD_CTRL(NO_PAD_CTRL),
/* Power */
IMX8MQ_PAD_GPIO1_IO00__GPIO1_IO0 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
static void setup_iomux_fec(void)
{
imx_iomux_v3_setup_multiple_pads(fec1_pads, ARRAY_SIZE(fec1_pads));
gpio_request(IMX_GPIO_NR(1, 0), "fec1_pwr");
gpio_direction_output(IMX_GPIO_NR(1, 0), 1);
udelay(500);
gpio_request(IMX_GPIO_NR(1, 9), "fec1_rst");
gpio_direction_output(IMX_GPIO_NR(1, 9), 0);
udelay(500);
gpio_direction_output(IMX_GPIO_NR(1, 9), 1);
}
static int setup_fec(void)
{
struct iomuxc_gpr_base_regs *gpr =
(struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
setup_iomux_fec();
/* Use 125M anatop REF_CLK1 for ENET1, not from external */
clrsetbits_le32(&gpr->gpr[1], BIT(13) | BIT(17), 0);
return set_clk_enet(ENET_125MHZ);
}
int board_phy_config(struct phy_device *phydev)
{
/* enable rgmii rxc skew and phy mode select to RGMII copper */
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x8);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
if (phydev->drv->config)
phydev->drv->config(phydev);
return 0;
}
#endif
int board_init(void)
{
#ifdef CONFIG_FEC_MXC
setup_fec();
#endif
return 0;
}
int board_mmc_get_env_dev(int devno)
{
return devno;
}
int board_late_init(void)
{
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
env_set("board_rev", "iMX8MQ");
#endif
return 0;
}

View file

@ -0,0 +1,223 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018 NXP
*/
#include <common.h>
#include <hang.h>
#include <asm/arch/clock.h>
#include <asm/arch/ddr.h>
#include <asm/arch/imx8mq_pins.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
#include <asm/mach-imx/gpio.h>
#include <asm/mach-imx/iomux-v3.h>
#include <asm/mach-imx/mxc_i2c.h>
#include <errno.h>
#include <fsl_esdhc_imx.h>
#include <mmc.h>
#include <spl.h>
#include "lpddr4_timing.h"
DECLARE_GLOBAL_DATA_PTR;
#define DDR_DET_1 IMX_GPIO_NR(3, 11)
#define DDR_DET_2 IMX_GPIO_NR(3, 12)
#define DDR_DET_3 IMX_GPIO_NR(3, 13)
static iomux_v3_cfg_t const verdet_pads[] = {
IMX8MQ_PAD_NAND_DATA01__GPIO3_IO7 | MUX_PAD_CTRL(NO_PAD_CTRL),
IMX8MQ_PAD_NAND_DATA02__GPIO3_IO8 | MUX_PAD_CTRL(NO_PAD_CTRL),
IMX8MQ_PAD_NAND_DATA03__GPIO3_IO9 | MUX_PAD_CTRL(NO_PAD_CTRL),
IMX8MQ_PAD_NAND_DATA04__GPIO3_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
IMX8MQ_PAD_NAND_DATA05__GPIO3_IO11 | MUX_PAD_CTRL(NO_PAD_CTRL),
IMX8MQ_PAD_NAND_DATA06__GPIO3_IO12 | MUX_PAD_CTRL(NO_PAD_CTRL),
IMX8MQ_PAD_NAND_DATA07__GPIO3_IO13 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
/*
* DDR_DET_1 DDR_DET_2 DDR_DET_3
* 0 0 1 4G LPDDR4
* 1 1 1 3G LPDDR4
* 1 1 0 2G LPDDR4
* 1 0 1 1G LPDDR4
*/
static void spl_dram_init(void)
{
struct dram_timing_info *dram_timing;
u8 ddr = 0, size;
imx_iomux_v3_setup_multiple_pads(verdet_pads, ARRAY_SIZE(verdet_pads));
gpio_request(DDR_DET_1, "ddr_det_1");
gpio_direction_input(DDR_DET_1);
gpio_request(DDR_DET_2, "ddr_det_2");
gpio_direction_input(DDR_DET_2);
gpio_request(DDR_DET_3, "ddr_det_3");
gpio_direction_input(DDR_DET_3);
ddr |= !!gpio_get_value(DDR_DET_3) << 0;
ddr |= !!gpio_get_value(DDR_DET_2) << 1;
ddr |= !!gpio_get_value(DDR_DET_1) << 2;
switch (ddr) {
case 0x1:
size = 4;
dram_timing = &dram_timing_4gb;
break;
case 0x7:
size = 3;
dram_timing = &dram_timing_3gb;
break;
case 0x6:
size = 2;
dram_timing = &dram_timing_2gb;
break;
case 0x5:
size = 1;
dram_timing = &dram_timing_1gb;
break;
default:
puts("Unknown DDR type!!!\n");
return;
}
printf("%s: LPDDR4 %d GiB\n", __func__, size);
ddr_init(dram_timing);
writel(size, M4_BOOTROM_BASE_ADDR);
}
#define USDHC2_CD_GPIO IMX_GPIO_NR(2, 12)
#define USDHC1_PWR_GPIO IMX_GPIO_NR(2, 10)
#define USDHC2_PWR_GPIO IMX_GPIO_NR(2, 19)
int board_mmc_getcd(struct mmc *mmc)
{
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
int ret = 0;
switch (cfg->esdhc_base) {
case USDHC1_BASE_ADDR:
ret = 1;
break;
case USDHC2_BASE_ADDR:
ret = !gpio_get_value(USDHC2_CD_GPIO);
return ret;
}
return 1;
}
#define USDHC_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE | \
PAD_CTL_FSEL2)
#define USDHC_GPIO_PAD_CTRL (PAD_CTL_PUE | PAD_CTL_DSE1)
static iomux_v3_cfg_t const usdhc1_pads[] = {
IMX8MQ_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA0__USDHC1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA1__USDHC1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA2__USDHC1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA3__USDHC1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA4__USDHC1_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA5__USDHC1_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA6__USDHC1_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA7__USDHC1_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_RESET_B__GPIO2_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
static iomux_v3_cfg_t const usdhc2_pads[] = {
IMX8MQ_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD2_DATA0__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD2_DATA1__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD2_DATA2__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD2_DATA3__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD2_CD_B__GPIO2_IO12 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL),
IMX8MQ_PAD_SD2_RESET_B__GPIO2_IO19 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL),
};
static struct fsl_esdhc_cfg usdhc_cfg[2] = {
{USDHC1_BASE_ADDR, 0, 8},
{USDHC2_BASE_ADDR, 0, 4},
};
int board_mmc_init(bd_t *bis)
{
int ret;
/*
* According to the board_mmc_init() the following map is done:
* (U-Boot device node) (Physical Port)
* mmc0 USDHC1
* mmc1 USDHC2
*/
init_clk_usdhc(0);
usdhc_cfg[0].sdhc_clk = mxc_get_clock(USDHC1_CLK_ROOT);
imx_iomux_v3_setup_multiple_pads(usdhc1_pads, ARRAY_SIZE(usdhc1_pads));
gpio_request(USDHC1_PWR_GPIO, "usdhc1_reset");
gpio_direction_output(USDHC1_PWR_GPIO, 0);
udelay(500);
gpio_direction_output(USDHC1_PWR_GPIO, 1);
ret = fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
if (ret)
return ret;
init_clk_usdhc(1);
usdhc_cfg[1].sdhc_clk = mxc_get_clock(USDHC2_CLK_ROOT);
imx_iomux_v3_setup_multiple_pads(usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
gpio_request(USDHC2_PWR_GPIO, "usdhc2_reset");
gpio_direction_output(USDHC2_PWR_GPIO, 0);
udelay(500);
gpio_direction_output(USDHC2_PWR_GPIO, 1);
return fsl_esdhc_initialize(bis, &usdhc_cfg[1]);
}
void spl_board_init(void)
{
puts("Normal Boot\n");
}
#ifdef CONFIG_SPL_LOAD_FIT
int board_fit_config_name_match(const char *name)
{
/* Just empty function now - can't decide what to choose */
debug("%s: %s\n", __func__, name);
return 0;
}
#endif
void board_init_f(ulong dummy)
{
int ret;
/* Clear global data */
memset((void *)gd, 0, sizeof(gd_t));
arch_cpu_init();
init_uart_clk(0);
board_early_init_f();
timer_init();
preloader_console_init();
/* Clear the BSS. */
memset(__bss_start, 0, __bss_end - __bss_start);
ret = spl_init();
if (ret) {
debug("spl_init() failed: %d\n", ret);
hang();
}
enable_tzc380();
/* DDR initialization */
spl_dram_init();
board_init_r(NULL, 0);
}

View file

@ -183,11 +183,11 @@ static int print_cpuinfo(void)
char desc[512];
int ret;
ret = uclass_first_device_err(UCLASS_CPU, &dev);
if (ret) {
debug("%s: Could not get CPU device (err = %d)\n",
__func__, ret);
return ret;
dev = cpu_get_current_dev();
if (!dev) {
debug("%s: Could not get CPU device\n",
__func__);
return -ENODEV;
}
ret = cpu_get_desc(dev, desc, sizeof(desc));

View file

@ -1172,6 +1172,14 @@ config SPL_USB_SDP_SUPPORT
Enable Serial Download Protocol (SDP) device support in SPL. This
allows to download images into memory and execute (jump to) them
using the same protocol as implemented by the i.MX family's boot ROM.
config SPL_SDP_USB_DEV
int "SDP USB controller index"
default 0
depends on SPL_USB_SDP_SUPPORT
help
Some boards have USB controller other than 0. Define this option
so it can be used in compiled environment.
endif
config SPL_WATCHDOG_SUPPORT

View file

@ -14,7 +14,9 @@ static int spl_sdp_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
int ret;
const int controller_index = 0;
const int controller_index = CONFIG_SPL_SDP_USB_DEV;
usb_gadget_initialize(controller_index);
g_dnl_clear_detach();
ret = g_dnl_register("usb_dnl_sdp");
@ -37,6 +39,7 @@ static int spl_sdp_load_image(struct spl_image_info *spl_image,
ret = spl_sdp_handle(controller_index, spl_image);
debug("SDP ended\n");
usb_gadget_release(controller_index);
return ret;
}
SPL_LOAD_IMAGE_METHOD("USB SDP", 0, BOOT_DEVICE_BOARD, spl_sdp_load_image);

View file

@ -0,0 +1,104 @@
CONFIG_ARM=y
CONFIG_ARCH_IMX8M=y
CONFIG_SYS_TEXT_BASE=0x40200000
CONFIG_SPL_GPIO_SUPPORT=y
CONFIG_SPL_LIBCOMMON_SUPPORT=y
CONFIG_SPL_LIBGENERIC_SUPPORT=y
CONFIG_SYS_MALLOC_F_LEN=0x10000
CONFIG_ENV_SIZE=0x1000
CONFIG_ENV_OFFSET=0x400000
CONFIG_SYS_I2C_MXC_I2C1=y
CONFIG_SYS_I2C_MXC_I2C2=y
CONFIG_SYS_I2C_MXC_I2C3=y
CONFIG_DM_GPIO=y
CONFIG_TARGET_IMX8MM_BEACON=y
CONFIG_SPL_MMC_SUPPORT=y
CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
CONFIG_SPL=y
CONFIG_SPL_TEXT_BASE=0x7E1000
CONFIG_FIT=y
CONFIG_FIT_EXTERNAL_OFFSET=0x3000
CONFIG_SPL_LOAD_FIT=y
CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-imx/mkimage_fit_atf.sh"
CONFIG_OF_SYSTEM_SETUP=y
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/imx8m/imximage-8mm-lpddr4.cfg"
CONFIG_DEFAULT_FDT_FILE="imx8mm-beacon-kit.dtb"
CONFIG_SPL_BOARD_INIT=y
CONFIG_SPL_SEPARATE_BSS=y
CONFIG_SPL_I2C_SUPPORT=y
CONFIG_SPL_POWER_SUPPORT=y
CONFIG_SPL_WATCHDOG_SUPPORT=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="u-boot=> "
# CONFIG_CMD_EXPORTENV is not set
# CONFIG_CMD_IMPORTENV is not set
# CONFIG_CMD_CRC32 is not set
CONFIG_CMD_CLK=y
CONFIG_CMD_FUSE=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
CONFIG_CMD_PART=y
CONFIG_CMD_DHCP=y
CONFIG_CMD_MII=y
CONFIG_CMD_PING=y
CONFIG_CMD_CACHE=y
CONFIG_CMD_PMIC=y
CONFIG_CMD_REGULATOR=y
CONFIG_CMD_EXT2=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_FAT=y
CONFIG_OF_CONTROL=y
CONFIG_SPL_OF_CONTROL=y
CONFIG_DEFAULT_DEVICE_TREE="imx8mm-beacon-kit"
CONFIG_ENV_IS_IN_MMC=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_DM=y
CONFIG_SPL_CLK_COMPOSITE_CCF=y
CONFIG_CLK_COMPOSITE_CCF=y
CONFIG_SPL_CLK_IMX8MM=y
CONFIG_CLK_IMX8MM=y
CONFIG_MXC_GPIO=y
CONFIG_DM_PCA953X=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_MXC=y
CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_FSL_USDHC=y
CONFIG_PHYLIB=y
CONFIG_PHY_ATHEROS=y
CONFIG_DM_ETH=y
CONFIG_PHY_GIGE=y
CONFIG_FEC_MXC=y
CONFIG_MII=y
CONFIG_PINCTRL=y
CONFIG_SPL_PINCTRL=y
CONFIG_PINCTRL_IMX8M=y
CONFIG_DM_PMIC=y
CONFIG_DM_PMIC_BD71837=y
CONFIG_SPL_DM_PMIC_BD71837=y
CONFIG_DM_REGULATOR=y
CONFIG_SPL_DM_REGULATOR=y
CONFIG_DM_REGULATOR_BD71837=y
CONFIG_SPL_DM_REGULATOR_BD71837=y
CONFIG_DM_REGULATOR_FIXED=y
CONFIG_DM_REGULATOR_GPIO=y
CONFIG_CONS_INDEX=2
CONFIG_DM_SERIAL=y
# CONFIG_SPL_DM_SERIAL is not set
CONFIG_MXC_UART=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
CONFIG_SPI_MEM=y
CONFIG_NXP_FSPI=y
CONFIG_SYSRESET=y
CONFIG_SPL_SYSRESET=y
CONFIG_SYSRESET_PSCI=y
CONFIG_SYSRESET_WATCHDOG=y
CONFIG_DM_THERMAL=y
# CONFIG_WATCHDOG is not set
CONFIG_IMX_WATCHDOG=y

View file

@ -1,6 +1,4 @@
CONFIG_ARM=y
CONFIG_SPL_SYS_ICACHE_OFF=y
CONFIG_SPL_SYS_DCACHE_OFF=y
CONFIG_ARCH_IMX8M=y
CONFIG_SYS_TEXT_BASE=0x40200000
CONFIG_SYS_MALLOC_F_LEN=0x4000

View file

@ -0,0 +1,47 @@
CONFIG_ARM=y
CONFIG_ARCH_IMX8M=y
CONFIG_SYS_TEXT_BASE=0x40200000
CONFIG_ENV_SIZE=0x1000
CONFIG_ENV_OFFSET=0x400000
CONFIG_DM_GPIO=y
CONFIG_TARGET_PICO_IMX8MQ=y
CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL=y
CONFIG_CSF_SIZE=0x2000
CONFIG_SPL_TEXT_BASE=0x7E1000
CONFIG_FIT=y
CONFIG_FIT_EXTERNAL_OFFSET=0x3000
CONFIG_SPL_LOAD_FIT=y
CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-imx/mkimage_fit_atf.sh"
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/imx8m/imximage.cfg"
CONFIG_SPL_BOARD_INIT=y
CONFIG_HUSH_PARSER=y
# CONFIG_BOOTM_NETBSD is not set
CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
CONFIG_CMD_CACHE=y
CONFIG_CMD_REGULATOR=y
CONFIG_CMD_EXT2=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_FAT=y
CONFIG_OF_CONTROL=y
CONFIG_DEFAULT_DEVICE_TREE="imx8mq-pico-pi"
CONFIG_ENV_IS_IN_MMC=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SAVED_DRAM_TIMING_BASE=0x40000000
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_MXC=y
CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_FSL_USDHC=y
CONFIG_DM_ETH=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_IMX8M=y
CONFIG_POWER_DOMAIN=y
CONFIG_IMX8M_POWER_DOMAIN=y
CONFIG_DM_REGULATOR=y
CONFIG_DM_REGULATOR_FIXED=y
CONFIG_DM_REGULATOR_GPIO=y
CONFIG_DM_RESET=y
CONFIG_DM_THERMAL=y

View file

@ -10,6 +10,7 @@
#include <errno.h>
#include <dm/lists.h>
#include <dm/root.h>
#include <linux/err.h>
int cpu_probe_all(void)
{
@ -34,6 +35,39 @@ int cpu_probe_all(void)
return 0;
}
int cpu_is_current(struct udevice *cpu)
{
struct cpu_ops *ops = cpu_get_ops(cpu);
if (ops->is_current) {
if (ops->is_current(cpu))
return 1;
}
return -ENOSYS;
}
struct udevice *cpu_get_current_dev(void)
{
struct udevice *cpu;
int ret;
uclass_foreach_dev_probe(UCLASS_CPU, cpu) {
if (cpu_is_current(cpu) > 0)
return cpu;
}
/* If can't find current cpu device, use the first dev instead */
ret = uclass_first_device_err(UCLASS_CPU, &cpu);
if (ret) {
debug("%s: Could not get CPU device (err = %d)\n",
__func__, ret);
return NULL;
}
return cpu;
}
int cpu_get_desc(struct udevice *dev, char *buf, int size)
{
struct cpu_ops *ops = cpu_get_ops(dev);

View file

@ -36,11 +36,20 @@ int cpu_sandbox_get_vendor(struct udevice *dev, char *buf, int size)
return 0;
}
int cpu_sandbox_is_current(struct udevice *dev)
{
if (!strcmp(dev->name, "cpu-test1"))
return 1;
return 0;
}
static const struct cpu_ops cpu_sandbox_ops = {
.get_desc = cpu_sandbox_get_desc,
.get_info = cpu_sandbox_get_info,
.get_count = cpu_sandbox_get_count,
.get_vendor = cpu_sandbox_get_vendor,
.is_current = cpu_sandbox_is_current,
};
int cpu_sandbox_probe(struct udevice *dev)

View file

@ -20,6 +20,7 @@ struct cpu_imx_platdata {
const char *type;
u32 cpurev;
u32 freq_mhz;
u32 mpidr;
};
const char *get_imx8_type(u32 imxtype)
@ -42,31 +43,35 @@ const char *get_imx8_rev(u32 rev)
return "A";
case CHIP_REV_B:
return "B";
case CHIP_REV_C:
return "C";
default:
return "?";
}
}
const char *get_core_name(void)
const char *get_core_name(struct udevice *dev)
{
if (is_cortex_a35())
if (!device_is_compatible(dev, "arm,cortex-a35"))
return "A35";
else if (is_cortex_a53())
else if (!device_is_compatible(dev, "arm,cortex-a53"))
return "A53";
else if (is_cortex_a72())
else if (!device_is_compatible(dev, "arm,cortex-a72"))
return "A72";
else
return "?";
}
#if IS_ENABLED(CONFIG_IMX_SCU_THERMAL)
static int cpu_imx_get_temp(void)
static int cpu_imx_get_temp(struct cpu_imx_platdata *plat)
{
struct udevice *thermal_dev;
int cpu_tmp, ret;
ret = uclass_get_device_by_name(UCLASS_THERMAL, "cpu-thermal0",
&thermal_dev);
if (!strcmp(plat->name, "A72"))
ret = uclass_get_device(UCLASS_THERMAL, 1, &thermal_dev);
else
ret = uclass_get_device(UCLASS_THERMAL, 0, &thermal_dev);
if (!ret) {
ret = thermal_get_temp(thermal_dev, &cpu_tmp);
@ -79,7 +84,7 @@ static int cpu_imx_get_temp(void)
return cpu_tmp;
}
#else
static int cpu_imx_get_temp(void)
static int cpu_imx_get_temp(struct cpu_imx_platdata *plat)
{
return 0;
}
@ -88,7 +93,7 @@ static int cpu_imx_get_temp(void)
int cpu_imx_get_desc(struct udevice *dev, char *buf, int size)
{
struct cpu_imx_platdata *plat = dev_get_platdata(dev);
int ret;
int ret, temp;
if (size < 100)
return -ENOSPC;
@ -97,9 +102,13 @@ int cpu_imx_get_desc(struct udevice *dev, char *buf, int size)
plat->type, plat->rev, plat->name, plat->freq_mhz);
if (IS_ENABLED(CONFIG_IMX_SCU_THERMAL)) {
temp = cpu_imx_get_temp(plat);
buf = buf + ret;
size = size - ret;
ret = snprintf(buf, size, " at %dC", cpu_imx_get_temp());
if (temp != 0xdeadbeef)
ret = snprintf(buf, size, " at %dC", temp);
else
ret = snprintf(buf, size, " - invalid sensor data");
}
snprintf(buf + ret, size - ret, "\n");
@ -118,7 +127,24 @@ static int cpu_imx_get_info(struct udevice *dev, struct cpu_info *info)
static int cpu_imx_get_count(struct udevice *dev)
{
return 4;
ofnode node;
int num = 0;
ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) {
const char *device_type;
if (!ofnode_is_available(node))
continue;
device_type = ofnode_read_string(node, "device_type");
if (!device_type)
continue;
if (!strcmp(device_type, "cpu"))
num++;
}
return num;
}
static int cpu_imx_get_vendor(struct udevice *dev, char *buf, int size)
@ -127,25 +153,44 @@ static int cpu_imx_get_vendor(struct udevice *dev, char *buf, int size)
return 0;
}
static int cpu_imx_is_current(struct udevice *dev)
{
struct cpu_imx_platdata *plat = dev_get_platdata(dev);
if (plat->mpidr == (read_mpidr() & 0xffff))
return 1;
return 0;
}
static const struct cpu_ops cpu_imx8_ops = {
.get_desc = cpu_imx_get_desc,
.get_info = cpu_imx_get_info,
.get_count = cpu_imx_get_count,
.get_vendor = cpu_imx_get_vendor,
.is_current = cpu_imx_is_current,
};
static const struct udevice_id cpu_imx8_ids[] = {
{ .compatible = "arm,cortex-a35" },
{ .compatible = "arm,cortex-a53" },
{ .compatible = "arm,cortex-a72" },
{ }
};
static ulong imx8_get_cpu_rate(void)
static ulong imx8_get_cpu_rate(struct udevice *dev)
{
ulong rate;
int ret;
int type = is_cortex_a35() ? SC_R_A35 : is_cortex_a53() ?
SC_R_A53 : SC_R_A72;
int ret, type;
if (!device_is_compatible(dev, "arm,cortex-a35"))
type = SC_R_A35;
else if (!device_is_compatible(dev, "arm,cortex-a53"))
type = SC_R_A53;
else if (!device_is_compatible(dev, "arm,cortex-a72"))
type = SC_R_A72;
else
return 0;
ret = sc_pm_get_clock_rate(-1, type, SC_PM_CLK_CPU,
(sc_pm_clock_rate_t *)&rate);
@ -164,10 +209,16 @@ static int imx8_cpu_probe(struct udevice *dev)
cpurev = get_cpu_rev();
plat->cpurev = cpurev;
plat->name = get_core_name();
plat->name = get_core_name(dev);
plat->rev = get_imx8_rev(cpurev & 0xFFF);
plat->type = get_imx8_type((cpurev & 0xFF000) >> 12);
plat->freq_mhz = imx8_get_cpu_rate() / 1000000;
plat->freq_mhz = imx8_get_cpu_rate(dev) / 1000000;
plat->mpidr = dev_read_addr(dev);
if (plat->mpidr == FDT_ADDR_T_NONE) {
printf("%s: Failed to get CPU reg property\n", __func__);
return -EINVAL;
}
return 0;
}

View file

@ -44,7 +44,7 @@ config TI_EDMA3
config APBH_DMA
bool "Support APBH DMA"
depends on MX23 || MX28 || MX6 || MX7
depends on MX23 || MX28 || MX6 || MX7 || IMX8 || IMX8M
help
Enable APBH DMA driver.

View file

@ -7,6 +7,8 @@
*
* Based on code from LTIB:
* Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2017 NXP
*
*/
#include <cpu_func.h>
@ -88,7 +90,7 @@ void mxs_dma_flush_desc(struct mxs_dma_desc *desc)
uint32_t addr;
uint32_t size;
addr = (uint32_t)desc;
addr = (uintptr_t)desc;
size = roundup(sizeof(struct mxs_dma_desc), MXS_DMA_ALIGNMENT);
flush_dcache_range(addr, addr + size);
@ -215,16 +217,17 @@ static int mxs_dma_reset(int channel)
#if defined(CONFIG_MX23)
uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_ctrl0_set);
uint32_t offset = APBH_CTRL0_RESET_CHANNEL_OFFSET;
#elif (defined(CONFIG_MX28) || defined(CONFIG_MX6) || defined(CONFIG_MX7))
uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_channel_ctrl_set);
uint32_t offset = APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET;
#elif defined(CONFIG_MX28) || defined(CONFIG_MX6) || defined(CONFIG_MX7) || \
defined(CONFIG_IMX8) || defined(CONFIG_IMX8M)
u32 setreg = (uintptr_t)(&apbh_regs->hw_apbh_channel_ctrl_set);
u32 offset = APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET;
#endif
ret = mxs_dma_validate_chan(channel);
if (ret)
return ret;
writel(1 << (channel + offset), setreg);
writel(1 << (channel + offset), (uintptr_t)setreg);
return 0;
}

View file

@ -19,6 +19,7 @@
#include <dm/device_compat.h>
#include <linux/errno.h>
#include <asm/mach-imx/mxc_i2c.h>
#include <asm/mach-imx/sys_proto.h>
#include <asm/io.h>
#include <i2c.h>
#include <watchdog.h>
@ -747,6 +748,14 @@ void bus_i2c_init(int index, int speed, int unused,
return;
}
if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) {
if (i2c_fused((ulong)mxc_i2c_buses[index].base)) {
printf("SoC fuse indicates I2C@0x%lx is unavailable.\n",
(ulong)mxc_i2c_buses[index].base);
return;
}
}
/*
* Warning: Be careful to allow the assignment to a static
* variable here. This function could be called while U-Boot is
@ -892,6 +901,14 @@ static int mxc_i2c_probe(struct udevice *bus)
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) {
if (i2c_fused((ulong)addr)) {
printf("SoC fuse indicates I2C@0x%lx is unavailable.\n",
(ulong)addr);
return -ENODEV;
}
}
i2c_bus->base = addr;
i2c_bus->index = bus->seq;
i2c_bus->bus = bus;

View file

@ -15,8 +15,13 @@ DECLARE_GLOBAL_DATA_PTR;
#define FSL_ECC_WORD_START_1 0x10
#define FSL_ECC_WORD_END_1 0x10F
#ifdef CONFIG_IMX8QM
#define FSL_ECC_WORD_START_2 0x1A0
#define FSL_ECC_WORD_END_2 0x1FF
#elif defined(CONFIG_IMX8QXP)
#define FSL_ECC_WORD_START_2 0x220
#define FSL_ECC_WORD_END_2 0x31F
#endif
#define FSL_QXP_FUSE_GAP_START 0x110
#define FSL_QXP_FUSE_GAP_END 0x21F

View file

@ -74,7 +74,7 @@ static int mu_hal_receivemsg(struct mu_type *base, u32 reg_index, u32 *msg)
assert(reg_index < MU_TR_COUNT);
/* Wait RX register to be full. */
ret = readl_poll_timeout(&base->sr, val, val & mask, 10000);
ret = readl_poll_timeout(&base->sr, val, val & mask, 1000000);
if (ret < 0) {
printf("%s timeout\n", __func__);
return -ETIMEDOUT;

View file

@ -259,12 +259,12 @@ config NAND_MXC
config NAND_MXS
bool "MXS NAND support"
depends on MX23 || MX28 || MX6 || MX7
depends on MX23 || MX28 || MX6 || MX7 || IMX8 || IMX8M
select SYS_NAND_SELF_INIT
imply CMD_NAND
select APBH_DMA
select APBH_DMA_BURST if ARCH_MX6 || ARCH_MX7
select APBH_DMA_BURST8 if ARCH_MX6 || ARCH_MX7
select APBH_DMA_BURST if ARCH_MX6 || ARCH_MX7 || ARCH_IMX8 || ARCH_IMX8M
select APBH_DMA_BURST8 if ARCH_MX6 || ARCH_MX7 || ARCH_IMX8 || ARCH_IMX8M
help
This enables NAND driver for the NAND flash controller on the
MXS processors.

View file

@ -10,6 +10,7 @@
*
* Copyright (C) 2010 Freescale Semiconductor, Inc.
* Copyright (C) 2008 Embedded Alley Solutions, Inc.
* Copyright 2017-2019 NXP
*/
#include <common.h>
@ -30,7 +31,8 @@
#define MXS_NAND_DMA_DESCRIPTOR_COUNT 4
#if (defined(CONFIG_MX6) || defined(CONFIG_MX7))
#if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8) || \
defined(CONFIG_IMX8M)
#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT 2
#else
#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT 0
@ -54,21 +56,21 @@ struct nand_ecclayout fake_ecc_layout;
#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
static void mxs_nand_flush_data_buf(struct mxs_nand_info *info)
{
uint32_t addr = (uint32_t)info->data_buf;
uint32_t addr = (uintptr_t)info->data_buf;
flush_dcache_range(addr, addr + info->data_buf_size);
}
static void mxs_nand_inval_data_buf(struct mxs_nand_info *info)
{
uint32_t addr = (uint32_t)info->data_buf;
uint32_t addr = (uintptr_t)info->data_buf;
invalidate_dcache_range(addr, addr + info->data_buf_size);
}
static void mxs_nand_flush_cmd_buf(struct mxs_nand_info *info)
{
uint32_t addr = (uint32_t)info->cmd_buf;
uint32_t addr = (uintptr_t)info->cmd_buf;
flush_dcache_range(addr, addr + MXS_NAND_COMMAND_BUFFER_SIZE);
}
@ -112,53 +114,32 @@ static uint32_t mxs_nand_aux_status_offset(void)
return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
}
static inline int mxs_nand_calc_mark_offset(struct bch_geometry *geo,
uint32_t page_data_size)
static inline bool mxs_nand_bbm_in_data_chunk(struct bch_geometry *geo, struct mtd_info *mtd,
unsigned int *chunk_num)
{
uint32_t chunk_data_size_in_bits = geo->ecc_chunk_size * 8;
uint32_t chunk_ecc_size_in_bits = geo->ecc_strength * geo->gf_len;
uint32_t chunk_total_size_in_bits;
uint32_t block_mark_chunk_number;
uint32_t block_mark_chunk_bit_offset;
uint32_t block_mark_bit_offset;
unsigned int i, j;
chunk_total_size_in_bits =
chunk_data_size_in_bits + chunk_ecc_size_in_bits;
if (geo->ecc_chunk0_size != geo->ecc_chunkn_size) {
dev_err(this->dev, "The size of chunk0 must equal to chunkn\n");
return false;
}
/* Compute the bit offset of the block mark within the physical page. */
block_mark_bit_offset = page_data_size * 8;
i = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8) /
(geo->gf_len * geo->ecc_strength +
geo->ecc_chunkn_size * 8);
/* Subtract the metadata bits. */
block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
j = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8) -
(geo->gf_len * geo->ecc_strength +
geo->ecc_chunkn_size * 8) * i;
/*
* Compute the chunk number (starting at zero) in which the block mark
* appears.
*/
block_mark_chunk_number =
block_mark_bit_offset / chunk_total_size_in_bits;
if (j < geo->ecc_chunkn_size * 8) {
*chunk_num = i + 1;
dev_dbg(this->dev, "Set ecc to %d and bbm in chunk %d\n",
geo->ecc_strength, *chunk_num);
return true;
}
/*
* Compute the bit offset of the block mark within its chunk, and
* validate it.
*/
block_mark_chunk_bit_offset = block_mark_bit_offset -
(block_mark_chunk_number * chunk_total_size_in_bits);
if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
return -EINVAL;
/*
* Now that we know the chunk number in which the block mark appears,
* we can subtract all the ECC bits that appear before it.
*/
block_mark_bit_offset -=
block_mark_chunk_number * chunk_ecc_size_in_bits;
geo->block_mark_byte_offset = block_mark_bit_offset >> 3;
geo->block_mark_bit_offset = block_mark_bit_offset & 0x7;
return 0;
return false;
}
static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
@ -168,6 +149,7 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
unsigned int block_mark_bit_offset;
switch (ecc_step) {
case SZ_512:
@ -180,45 +162,51 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
return -EINVAL;
}
geo->ecc_chunk_size = ecc_step;
geo->ecc_chunk0_size = ecc_step;
geo->ecc_chunkn_size = ecc_step;
geo->ecc_strength = round_up(ecc_strength, 2);
/* Keep the C >= O */
if (geo->ecc_chunk_size < mtd->oobsize)
if (geo->ecc_chunkn_size < mtd->oobsize)
return -EINVAL;
if (geo->ecc_strength > nand_info->max_ecc_strength_supported)
return -EINVAL;
geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
/* For bit swap. */
block_mark_bit_offset = mtd->writesize * 8 -
(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+ MXS_NAND_METADATA_SIZE * 8);
geo->block_mark_byte_offset = block_mark_bit_offset / 8;
geo->block_mark_bit_offset = block_mark_bit_offset % 8;
return 0;
}
static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo,
static inline int mxs_nand_legacy_calc_ecc_layout(struct bch_geometry *geo,
struct mtd_info *mtd)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
unsigned int block_mark_bit_offset;
/* The default for the length of Galois Field. */
geo->gf_len = 13;
/* The default for chunk size. */
geo->ecc_chunk_size = 512;
geo->ecc_chunk0_size = 512;
geo->ecc_chunkn_size = 512;
if (geo->ecc_chunk_size < mtd->oobsize) {
if (geo->ecc_chunkn_size < mtd->oobsize) {
geo->gf_len = 14;
geo->ecc_chunk_size *= 2;
geo->ecc_chunk0_size *= 2;
geo->ecc_chunkn_size *= 2;
}
if (mtd->oobsize > geo->ecc_chunk_size) {
printf("Not support the NAND chips whose oob size is larger then %d bytes!\n",
geo->ecc_chunk_size);
return -EINVAL;
}
geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
/*
* Determine the ECC layout with the formula:
@ -234,6 +222,84 @@ static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo,
geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
nand_info->max_ecc_strength_supported);
block_mark_bit_offset = mtd->writesize * 8 -
(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+ MXS_NAND_METADATA_SIZE * 8);
geo->block_mark_byte_offset = block_mark_bit_offset / 8;
geo->block_mark_bit_offset = block_mark_bit_offset % 8;
return 0;
}
static inline int mxs_nand_calc_ecc_for_large_oob(struct bch_geometry *geo,
struct mtd_info *mtd)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
unsigned int block_mark_bit_offset;
unsigned int max_ecc;
unsigned int bbm_chunk;
unsigned int i;
/* sanity check for the minimum ecc nand required */
if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
return -EINVAL;
geo->ecc_strength = chip->ecc_strength_ds;
/* calculate the maximum ecc platform can support*/
geo->gf_len = 14;
geo->ecc_chunk0_size = 1024;
geo->ecc_chunkn_size = 1024;
geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
max_ecc = ((mtd->oobsize - MXS_NAND_METADATA_SIZE) * 8)
/ (geo->gf_len * geo->ecc_chunk_count);
max_ecc = min(round_down(max_ecc, 2),
nand_info->max_ecc_strength_supported);
/* search a supported ecc strength that makes bbm */
/* located in data chunk */
geo->ecc_strength = chip->ecc_strength_ds;
while (!(geo->ecc_strength > max_ecc)) {
if (mxs_nand_bbm_in_data_chunk(geo, mtd, &bbm_chunk))
break;
geo->ecc_strength += 2;
}
/* if none of them works, keep using the minimum ecc */
/* nand required but changing ecc page layout */
if (geo->ecc_strength > max_ecc) {
geo->ecc_strength = chip->ecc_strength_ds;
/* add extra ecc for meta data */
geo->ecc_chunk0_size = 0;
geo->ecc_chunk_count = (mtd->writesize / geo->ecc_chunkn_size) + 1;
geo->ecc_for_meta = 1;
/* check if oob can afford this extra ecc chunk */
if (mtd->oobsize * 8 < MXS_NAND_METADATA_SIZE * 8 +
geo->gf_len * geo->ecc_strength
* geo->ecc_chunk_count) {
printf("unsupported NAND chip with new layout\n");
return -EINVAL;
}
/* calculate in which chunk bbm located */
bbm_chunk = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8 -
geo->gf_len * geo->ecc_strength) /
(geo->gf_len * geo->ecc_strength +
geo->ecc_chunkn_size * 8) + 1;
}
/* calculate the number of ecc chunk behind the bbm */
i = (mtd->writesize / geo->ecc_chunkn_size) - bbm_chunk + 1;
block_mark_bit_offset = mtd->writesize * 8 -
(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - i)
+ MXS_NAND_METADATA_SIZE * 8);
geo->block_mark_byte_offset = block_mark_bit_offset / 8;
geo->block_mark_bit_offset = block_mark_bit_offset % 8;
return 0;
}
@ -548,6 +614,45 @@ static uint8_t mxs_nand_read_byte(struct mtd_info *mtd)
return buf;
}
static bool mxs_nand_erased_page(struct mtd_info *mtd, struct nand_chip *nand,
u8 *buf, int chunk, int page)
{
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
struct bch_geometry *geo = &nand_info->bch_geometry;
unsigned int flip_bits = 0, flip_bits_noecc = 0;
unsigned int threshold;
unsigned int base = geo->ecc_chunkn_size * chunk;
u32 *dma_buf = (u32 *)buf;
int i;
threshold = geo->gf_len / 2;
if (threshold > geo->ecc_strength)
threshold = geo->ecc_strength;
for (i = 0; i < geo->ecc_chunkn_size; i++) {
flip_bits += hweight8(~buf[base + i]);
if (flip_bits > threshold)
return false;
}
nand->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
nand->read_buf(mtd, buf, mtd->writesize);
for (i = 0; i < mtd->writesize / 4; i++) {
flip_bits_noecc += hweight32(~dma_buf[i]);
if (flip_bits_noecc > threshold)
return false;
}
mtd->ecc_stats.corrected += flip_bits;
memset(buf, 0xff, mtd->writesize);
printf("The page(%d) is an erased page(%d,%d,%d,%d).\n", page, chunk, threshold, flip_bits, flip_bits_noecc);
return true;
}
/*
* Read a page from NAND.
*/
@ -557,11 +662,13 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
{
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
struct bch_geometry *geo = &nand_info->bch_geometry;
struct mxs_bch_regs *bch_regs = nand_info->bch_regs;
struct mxs_dma_desc *d;
uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
uint32_t corrected = 0, failed = 0;
uint8_t *status;
int i, ret;
int flag = 0;
/* Compile the DMA descriptor - wait for ready. */
d = mxs_nand_get_dma_desc(nand_info);
@ -603,6 +710,12 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
if (nand_info->en_randomizer) {
d->cmd.pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
GPMI_ECCCTRL_RANDOMIZER_TYPE2;
d->cmd.pio_words[3] |= (page % 256) << 16;
}
mxs_dma_desc_append(channel, d);
/* Compile the DMA descriptor - disable the BCH block. */
@ -651,6 +764,8 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
goto rtn;
}
mxs_nand_return_dma_descs(nand_info);
/* Invalidate caches */
mxs_nand_inval_data_buf(nand_info);
@ -663,10 +778,19 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
if (status[i] == 0x00)
continue;
if (status[i] == 0xff)
if (status[i] == 0xff) {
if (!nand_info->en_randomizer &&
(is_mx6dqp() || is_mx7() || is_mx6ul() ||
is_imx8() || is_imx8m()))
if (readl(&bch_regs->hw_bch_debug1))
flag = 1;
continue;
}
if (status[i] == 0xfe) {
if (mxs_nand_erased_page(mtd, nand,
nand_info->data_buf, i, page))
break;
failed++;
continue;
}
@ -693,6 +817,8 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
memcpy(buf, nand_info->data_buf, mtd->writesize);
if (flag)
memset(buf, 0xff, mtd->writesize);
rtn:
mxs_nand_return_dma_descs(nand_info);
@ -741,7 +867,7 @@ static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
if (is_mx7() && nand_info->en_randomizer) {
if (nand_info->en_randomizer) {
d->cmd.pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
GPMI_ECCCTRL_RANDOMIZER_TYPE2;
/*
@ -751,7 +877,7 @@ static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
* The value is between 0-255. For additional details
* check 9.6.6.4 of i.MX7D Applications Processor reference
*/
d->cmd.pio_words[3] |= (page % 255) << 16;
d->cmd.pio_words[3] |= (page % 256) << 16;
}
mxs_dma_desc_append(channel, d);
@ -983,19 +1109,24 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, struct bch_geometry *geo)
struct nand_chip *nand = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
if (chip->ecc.strength > 0 && chip->ecc.size > 0)
return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
chip->ecc.strength, chip->ecc.size);
if (nand_info->use_minimum_ecc ||
mxs_nand_calc_ecc_layout(geo, mtd)) {
if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
return -EINVAL;
return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
chip->ecc_strength_ds, chip->ecc_step_ds);
if (chip->ecc_strength_ds > nand_info->max_ecc_strength_supported) {
printf("unsupported NAND chip, minimum ecc required %d\n"
, chip->ecc_strength_ds);
return -EINVAL;
}
if ((!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
mtd->oobsize < 1024) || nand_info->legacy_bch_geometry) {
dev_warn(this->dev, "use legacy bch geometry\n");
return mxs_nand_legacy_calc_ecc_layout(geo, mtd);
}
if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
return mxs_nand_calc_ecc_for_large_oob(geo, mtd);
return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
chip->ecc_strength_ds, chip->ecc_step_ds);
return 0;
}
@ -1025,8 +1156,6 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
if (ret)
return ret;
mxs_nand_calc_mark_offset(geo, mtd->writesize);
/* Configure BCH and set NFC geometry */
mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
@ -1034,7 +1163,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
tmp = (geo->ecc_chunk_count - 1) << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
tmp |= (geo->ecc_strength >> 1) << BCH_FLASHLAYOUT0_ECC0_OFFSET;
tmp |= geo->ecc_chunk_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
tmp |= geo->ecc_chunk0_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
tmp |= (geo->gf_len == 14 ? 1 : 0) <<
BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
writel(tmp, &bch_regs->hw_bch_flash0layout0);
@ -1043,12 +1172,18 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
tmp = (mtd->writesize + mtd->oobsize)
<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
tmp |= (geo->ecc_strength >> 1) << BCH_FLASHLAYOUT1_ECCN_OFFSET;
tmp |= geo->ecc_chunk_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
tmp |= geo->ecc_chunkn_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
tmp |= (geo->gf_len == 14 ? 1 : 0) <<
BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
writel(tmp, &bch_regs->hw_bch_flash0layout1);
nand_info->bch_flash0layout1 = tmp;
/* Set erase threshold to ecc strength for mx6ul, mx6qp and mx7 */
if (is_mx6dqp() || is_mx7() ||
is_mx6ul() || is_imx8() || is_imx8m())
writel(BCH_MODE_ERASE_THRESHOLD(geo->ecc_strength),
&bch_regs->hw_bch_mode);
/* Set *all* chip selects to use layout 0 */
writel(0, &bch_regs->hw_bch_layoutselect);
@ -1184,7 +1319,7 @@ int mxs_nand_init_spl(struct nand_chip *nand)
nand_info->gpmi_regs = (struct mxs_gpmi_regs *)MXS_GPMI_BASE;
nand_info->bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
if (is_mx6sx() || is_mx7())
if (is_mx6sx() || is_mx7() || is_imx8() || is_imx8m())
nand_info->max_ecc_strength_supported = 62;
else
nand_info->max_ecc_strength_supported = 40;
@ -1268,7 +1403,7 @@ int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info)
nand->ecc.layout = &fake_ecc_layout;
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.size = nand_info->bch_geometry.ecc_chunk_size;
nand->ecc.size = nand_info->bch_geometry.ecc_chunkn_size;
nand->ecc.strength = nand_info->bch_geometry.ecc_strength;
/* second phase scan */
@ -1347,12 +1482,14 @@ void mxs_nand_get_layout(struct mtd_info *mtd, struct mxs_nand_layout *l)
BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET);
l->eccn = (tmp & BCH_FLASHLAYOUT1_ECCN_MASK) >>
BCH_FLASHLAYOUT1_ECCN_OFFSET;
l->gf_len = (tmp & BCH_FLASHLAYOUT1_GF13_0_GF14_1_MASK) >>
BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
}
/*
* Set BCH to specific layout used by ROM bootloader to read FCB.
*/
void mxs_nand_mode_fcb(struct mtd_info *mtd)
void mxs_nand_mode_fcb_62bit(struct mtd_info *mtd)
{
u32 tmp;
struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
@ -1385,6 +1522,43 @@ void mxs_nand_mode_fcb(struct mtd_info *mtd)
writel(tmp, &bch_regs->hw_bch_flash0layout1);
}
/*
* Set BCH to specific layout used by ROM bootloader to read FCB.
*/
void mxs_nand_mode_fcb_40bit(struct mtd_info *mtd)
{
u32 tmp;
struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
struct nand_chip *nand = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
/* no randomizer in this setting*/
nand_info->en_randomizer = 0;
mtd->writesize = 1024;
mtd->oobsize = 1576 - 1024;
/* 8 ecc_chunks_*/
tmp = 7 << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
/* 32 bytes for metadata */
tmp |= 32 << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
/* using ECC40 level to be performed */
tmp |= 0x14 << BCH_FLASHLAYOUT0_ECC0_OFFSET;
/* 0x20 * 4 bytes of the data0 block */
tmp |= 0x20 << BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET;
tmp |= 0 << BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
writel(tmp, &bch_regs->hw_bch_flash0layout0);
/* 1024 for data + 552 for OOB */
tmp = 1576 << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
/* using ECC40 level to be performed */
tmp |= 0x14 << BCH_FLASHLAYOUT1_ECCN_OFFSET;
/* 0x20 * 4 bytes of the data0 block */
tmp |= 0x20 << BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET;
tmp |= 0 << BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
writel(tmp, &bch_regs->hw_bch_flash0layout1);
}
/*
* Restore BCH to normal settings.
*/

View file

@ -2,6 +2,8 @@
* NXP GPMI NAND flash driver (DT initialization)
*
* Copyright (C) 2018 Toradex
* Copyright 2019 NXP
*
* Authors:
* Stefan Agner <stefan.agner@toradex.com>
*
@ -14,6 +16,7 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/printk.h>
#include <clk.h>
#include <mxs_nand.h>
@ -25,19 +28,39 @@ static const struct mxs_nand_dt_data mxs_nand_imx6q_data = {
.max_ecc_strength_supported = 40,
};
static const struct mxs_nand_dt_data mxs_nand_imx6sx_data = {
.max_ecc_strength_supported = 62,
};
static const struct mxs_nand_dt_data mxs_nand_imx7d_data = {
.max_ecc_strength_supported = 62,
};
static const struct mxs_nand_dt_data mxs_nand_imx8qxp_data = {
.max_ecc_strength_supported = 62,
};
static const struct udevice_id mxs_nand_dt_ids[] = {
{
.compatible = "fsl,imx6q-gpmi-nand",
.data = (unsigned long)&mxs_nand_imx6q_data,
},
{
.compatible = "fsl,imx6qp-gpmi-nand",
.data = (unsigned long)&mxs_nand_imx6q_data,
},
{
.compatible = "fsl,imx6sx-gpmi-nand",
.data = (unsigned long)&mxs_nand_imx6sx_data,
},
{
.compatible = "fsl,imx7d-gpmi-nand",
.data = (unsigned long)&mxs_nand_imx7d_data,
},
{
.compatible = "fsl,imx8qxp-gpmi-nand",
.data = (unsigned long)&mxs_nand_imx8qxp_data,
},
{ /* sentinel */ }
};
@ -69,6 +92,74 @@ static int mxs_nand_dt_probe(struct udevice *dev)
info->use_minimum_ecc = dev_read_bool(dev, "fsl,use-minimum-ecc");
info->legacy_bch_geometry = dev_read_bool(dev, "fsl,legacy-bch-geometry");
if (IS_ENABLED(CONFIG_CLK) && IS_ENABLED(CONFIG_IMX8)) {
/* Assigned clock already set clock */
struct clk gpmi_clk;
ret = clk_get_by_name(dev, "gpmi_io", &gpmi_clk);
if (ret < 0) {
debug("Can't get gpmi io clk: %d\n", ret);
return ret;
}
ret = clk_enable(&gpmi_clk);
if (ret < 0) {
debug("Can't enable gpmi io clk: %d\n", ret);
return ret;
}
ret = clk_get_by_name(dev, "gpmi_apb", &gpmi_clk);
if (ret < 0) {
debug("Can't get gpmi_apb clk: %d\n", ret);
return ret;
}
ret = clk_enable(&gpmi_clk);
if (ret < 0) {
debug("Can't enable gpmi_apb clk: %d\n", ret);
return ret;
}
ret = clk_get_by_name(dev, "gpmi_bch", &gpmi_clk);
if (ret < 0) {
debug("Can't get gpmi_bch clk: %d\n", ret);
return ret;
}
ret = clk_enable(&gpmi_clk);
if (ret < 0) {
debug("Can't enable gpmi_bch clk: %d\n", ret);
return ret;
}
ret = clk_get_by_name(dev, "gpmi_apb_bch", &gpmi_clk);
if (ret < 0) {
debug("Can't get gpmi_apb_bch clk: %d\n", ret);
return ret;
}
ret = clk_enable(&gpmi_clk);
if (ret < 0) {
debug("Can't enable gpmi_apb_bch clk: %d\n", ret);
return ret;
}
/* this clock is used for apbh_dma, since the apbh dma does not support DM,
* we optionally enable it here
*/
ret = clk_get_by_name(dev, "gpmi_apbh_dma", &gpmi_clk);
if (ret < 0) {
debug("Can't get gpmi_apbh_dma clk: %d\n", ret);
} else {
ret = clk_enable(&gpmi_clk);
if (ret < 0) {
debug("Can't enable gpmi_apbh_dma clk: %d\n", ret);
}
}
}
return mxs_nand_init_ctrl(info);
}

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2014 Gateworks Corporation
* Copyright 2019 NXP
* Author: Tim Harvey <tharvey@gateworks.com>
*/
#include <common.h>
@ -38,6 +39,12 @@ static void mxs_nand_command(struct mtd_info *mtd, unsigned int command,
if (command == NAND_CMD_READ0) {
chip->cmd_ctrl(mtd, NAND_CMD_READSTART, NAND_CLE);
chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0);
} else if (command == NAND_CMD_RNDOUT) {
/* No ready / busy check necessary */
chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART,
NAND_NCE | NAND_CLE);
chip->cmd_ctrl(mtd, NAND_CMD_NONE,
NAND_NCE);
}
/* wait for nand ready */
@ -212,23 +219,39 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
unsigned int page;
unsigned int nand_page_per_block;
unsigned int sz = 0;
u8 *page_buf = NULL;
u32 page_off;
chip = mtd_to_nand(mtd);
if (!chip->numchips)
return -ENODEV;
page_buf = malloc(mtd->writesize);
if (!page_buf)
return -ENOMEM;
page = offs >> chip->page_shift;
page_off = offs & (mtd->writesize - 1);
nand_page_per_block = mtd->erasesize / mtd->writesize;
debug("%s offset:0x%08x len:%d page:%d\n", __func__, offs, size, page);
debug("%s offset:0x%08x len:%d page:%x\n", __func__, offs, size, page);
size = roundup(size, mtd->writesize);
while (sz < size) {
if (mxs_read_page_ecc(mtd, buf, page) < 0)
while (size) {
if (mxs_read_page_ecc(mtd, page_buf, page) < 0)
return -1;
sz += mtd->writesize;
if (size > (mtd->writesize - page_off))
sz = (mtd->writesize - page_off);
else
sz = size;
memcpy(buf, page_buf + page_off, sz);
offs += mtd->writesize;
page++;
buf += mtd->writesize;
buf += (mtd->writesize - page_off);
page_off = 0;
size -= sz;
/*
* Check if we have crossed a block boundary, and if so
@ -242,12 +265,16 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
while (is_badblock(mtd, offs, 1)) {
page = page + nand_page_per_block;
/* Check i we've reached the end of flash. */
if (page >= mtd->size >> chip->page_shift)
if (page >= mtd->size >> chip->page_shift) {
free(page_buf);
return -ENOMEM;
}
}
}
}
free(page_buf);
return 0;
}

View file

@ -57,6 +57,12 @@ config MDIO_MUX_SANDBOX
This driver is used for testing in test/dm/mdio.c
config DM_ETH_PHY
bool "Enable Driver Model for Ethernet Generic PHY drivers"
depends on DM
help
Enable driver model for Ethernet Generic PHY .
menuconfig NETDEVICES
bool "Network device support"
depends on NET

View file

@ -20,6 +20,7 @@ obj-$(CONFIG_ETH_DESIGNWARE) += designware.o
obj-$(CONFIG_ETH_DESIGNWARE_SOCFPGA) += dwmac_socfpga.o
obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
obj-$(CONFIG_DNET) += dnet.o
obj-$(CONFIG_DM_ETH_PHY) += eth-phy-uclass.o
obj-$(CONFIG_E1000) += e1000.o
obj-$(CONFIG_E1000_SPI) += e1000_spi.o
obj-$(CONFIG_EEPRO100) += eepro100.o

View file

@ -41,6 +41,11 @@
#include <wait_bit.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <eth_phy.h>
#ifdef CONFIG_ARCH_IMX8M
#include <asm/arch/clock.h>
#include <asm/mach-imx/sys_proto.h>
#endif
/* Core registers */
@ -80,6 +85,7 @@ struct eqos_mac_regs {
#define EQOS_MAC_CONFIGURATION_PS BIT(15)
#define EQOS_MAC_CONFIGURATION_FES BIT(14)
#define EQOS_MAC_CONFIGURATION_DM BIT(13)
#define EQOS_MAC_CONFIGURATION_LM BIT(12)
#define EQOS_MAC_CONFIGURATION_TE BIT(1)
#define EQOS_MAC_CONFIGURATION_RE BIT(0)
@ -101,11 +107,19 @@ struct eqos_mac_regs {
#define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT 0
#define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK 0xff
#define EQOS_MAC_HW_FEATURE0_MMCSEL_SHIFT 8
#define EQOS_MAC_HW_FEATURE0_HDSEL_SHIFT 2
#define EQOS_MAC_HW_FEATURE0_GMIISEL_SHIFT 1
#define EQOS_MAC_HW_FEATURE0_MIISEL_SHIFT 0
#define EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT 6
#define EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_MASK 0x1f
#define EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT 0
#define EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK 0x1f
#define EQOS_MAC_HW_FEATURE3_ASP_SHIFT 28
#define EQOS_MAC_HW_FEATURE3_ASP_MASK 0x3
#define EQOS_MAC_MDIO_ADDRESS_PA_SHIFT 21
#define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT 16
#define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT 8
@ -153,6 +167,8 @@ struct eqos_mtl_regs {
#define EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK 0x3f
#define EQOS_MTL_RXQ0_OPERATION_MODE_EHFC BIT(7)
#define EQOS_MTL_RXQ0_OPERATION_MODE_RSF BIT(5)
#define EQOS_MTL_RXQ0_OPERATION_MODE_FEP BIT(4)
#define EQOS_MTL_RXQ0_OPERATION_MODE_FUP BIT(3)
#define EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT 16
#define EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK 0x7fff
@ -367,7 +383,7 @@ static void eqos_inval_desc_tegra186(void *desc)
#endif
}
static void eqos_inval_desc_stm32(void *desc)
static void eqos_inval_desc_generic(void *desc)
{
#ifndef CONFIG_SYS_NONCACHED_MEMORY
unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
@ -385,7 +401,7 @@ static void eqos_flush_desc_tegra186(void *desc)
#endif
}
static void eqos_flush_desc_stm32(void *desc)
static void eqos_flush_desc_generic(void *desc)
{
#ifndef CONFIG_SYS_NONCACHED_MEMORY
unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
@ -404,7 +420,7 @@ static void eqos_inval_buffer_tegra186(void *buf, size_t size)
invalidate_dcache_range(start, end);
}
static void eqos_inval_buffer_stm32(void *buf, size_t size)
static void eqos_inval_buffer_generic(void *buf, size_t size)
{
unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)buf + size,
@ -418,7 +434,7 @@ static void eqos_flush_buffer_tegra186(void *buf, size_t size)
flush_cache((unsigned long)buf, size);
}
static void eqos_flush_buffer_stm32(void *buf, size_t size)
static void eqos_flush_buffer_generic(void *buf, size_t size)
{
unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)buf + size,
@ -521,6 +537,7 @@ static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad,
static int eqos_start_clks_tegra186(struct udevice *dev)
{
#ifdef CONFIG_CLK
struct eqos_priv *eqos = dev_get_priv(dev);
int ret;
@ -561,10 +578,12 @@ static int eqos_start_clks_tegra186(struct udevice *dev)
pr_err("clk_enable(clk_tx) failed: %d", ret);
goto err_disable_clk_ptp_ref;
}
#endif
debug("%s: OK\n", __func__);
return 0;
#ifdef CONFIG_CLK
err_disable_clk_ptp_ref:
clk_disable(&eqos->clk_ptp_ref);
err_disable_clk_rx:
@ -576,10 +595,12 @@ err_disable_clk_slave_bus:
err:
debug("%s: FAILED: %d\n", __func__, ret);
return ret;
#endif
}
static int eqos_start_clks_stm32(struct udevice *dev)
{
#ifdef CONFIG_CLK
struct eqos_priv *eqos = dev_get_priv(dev);
int ret;
@ -610,10 +631,12 @@ static int eqos_start_clks_stm32(struct udevice *dev)
goto err_disable_clk_tx;
}
}
#endif
debug("%s: OK\n", __func__);
return 0;
#ifdef CONFIG_CLK
err_disable_clk_tx:
clk_disable(&eqos->clk_tx);
err_disable_clk_rx:
@ -623,10 +646,17 @@ err_disable_clk_master_bus:
err:
debug("%s: FAILED: %d\n", __func__, ret);
return ret;
#endif
}
static int eqos_start_clks_imx(struct udevice *dev)
{
return 0;
}
static void eqos_stop_clks_tegra186(struct udevice *dev)
{
#ifdef CONFIG_CLK
struct eqos_priv *eqos = dev_get_priv(dev);
debug("%s(dev=%p):\n", __func__, dev);
@ -636,12 +666,14 @@ static void eqos_stop_clks_tegra186(struct udevice *dev)
clk_disable(&eqos->clk_rx);
clk_disable(&eqos->clk_master_bus);
clk_disable(&eqos->clk_slave_bus);
#endif
debug("%s: OK\n", __func__);
}
static void eqos_stop_clks_stm32(struct udevice *dev)
{
#ifdef CONFIG_CLK
struct eqos_priv *eqos = dev_get_priv(dev);
debug("%s(dev=%p):\n", __func__, dev);
@ -651,10 +683,16 @@ static void eqos_stop_clks_stm32(struct udevice *dev)
clk_disable(&eqos->clk_master_bus);
if (clk_valid(&eqos->clk_ck))
clk_disable(&eqos->clk_ck);
#endif
debug("%s: OK\n", __func__);
}
static void eqos_stop_clks_imx(struct udevice *dev)
{
/* empty */
}
static int eqos_start_resets_tegra186(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
@ -722,6 +760,11 @@ static int eqos_start_resets_stm32(struct udevice *dev)
return 0;
}
static int eqos_start_resets_imx(struct udevice *dev)
{
return 0;
}
static int eqos_stop_resets_tegra186(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
@ -749,6 +792,11 @@ static int eqos_stop_resets_stm32(struct udevice *dev)
return 0;
}
static int eqos_stop_resets_imx(struct udevice *dev)
{
return 0;
}
static int eqos_calibrate_pads_tegra186(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
@ -803,16 +851,38 @@ static int eqos_disable_calibration_tegra186(struct udevice *dev)
static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev)
{
#ifdef CONFIG_CLK
struct eqos_priv *eqos = dev_get_priv(dev);
return clk_get_rate(&eqos->clk_slave_bus);
#else
return 0;
#endif
}
static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev)
{
#ifdef CONFIG_CLK
struct eqos_priv *eqos = dev_get_priv(dev);
return clk_get_rate(&eqos->clk_master_bus);
#else
return 0;
#endif
}
__weak u32 imx_get_eqos_csr_clk(void)
{
return 100 * 1000000;
}
__weak int imx_eqos_txclk_set_rate(unsigned long rate)
{
return 0;
}
static ulong eqos_get_tick_clk_rate_imx(struct udevice *dev)
{
return imx_get_eqos_csr_clk();
}
static int eqos_calibrate_pads_stm32(struct udevice *dev)
@ -820,11 +890,21 @@ static int eqos_calibrate_pads_stm32(struct udevice *dev)
return 0;
}
static int eqos_calibrate_pads_imx(struct udevice *dev)
{
return 0;
}
static int eqos_disable_calibration_stm32(struct udevice *dev)
{
return 0;
}
static int eqos_disable_calibration_imx(struct udevice *dev)
{
return 0;
}
static int eqos_set_full_duplex(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
@ -889,6 +969,7 @@ static int eqos_set_mii_speed_10(struct udevice *dev)
static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev)
{
#ifdef CONFIG_CLK
struct eqos_priv *eqos = dev_get_priv(dev);
ulong rate;
int ret;
@ -915,6 +996,7 @@ static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev)
pr_err("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret);
return ret;
}
#endif
return 0;
}
@ -924,6 +1006,38 @@ static int eqos_set_tx_clk_speed_stm32(struct udevice *dev)
return 0;
}
static int eqos_set_tx_clk_speed_imx(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
ulong rate;
int ret;
debug("%s(dev=%p):\n", __func__, dev);
switch (eqos->phy->speed) {
case SPEED_1000:
rate = 125 * 1000 * 1000;
break;
case SPEED_100:
rate = 25 * 1000 * 1000;
break;
case SPEED_10:
rate = 2.5 * 1000 * 1000;
break;
default:
pr_err("invalid speed %d", eqos->phy->speed);
return -EINVAL;
}
ret = imx_eqos_txclk_set_rate(rate);
if (ret < 0) {
pr_err("imx (tx_clk, %lu) failed: %d", rate, ret);
return ret;
}
return 0;
}
static int eqos_adjust_link(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
@ -1031,6 +1145,16 @@ static int eqos_write_hwaddr(struct udevice *dev)
return 0;
}
static int eqos_read_rom_hwaddr(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_platdata(dev);
#ifdef CONFIG_ARCH_IMX8M
imx_get_mac_from_fuse(dev->req_seq, pdata->enetaddr);
#endif
return !is_valid_ethaddr(pdata->enetaddr);
}
static int eqos_start(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
@ -1083,7 +1207,14 @@ static int eqos_start(struct udevice *dev)
* don't need to reconnect/reconfigure again
*/
if (!eqos->phy) {
eqos->phy = phy_connect(eqos->mii, eqos->phyaddr, dev,
int addr = -1;
#ifdef CONFIG_DM_ETH_PHY
addr = eth_phy_get_addr(dev);
#endif
#ifdef DWC_NET_PHYADDR
addr = DWC_NET_PHYADDR;
#endif
eqos->phy = phy_connect(eqos->mii, addr, dev,
eqos->config->interface(dev));
if (!eqos->phy) {
pr_err("phy_connect() failed");
@ -1123,6 +1254,7 @@ static int eqos_start(struct udevice *dev)
}
/* Configure MTL */
writel(0x60, &eqos->mtl_regs->txq0_quantum_weight - 0x100);
/* Enable Store and Forward mode for TX */
/* Program Tx operating mode */
@ -1136,7 +1268,9 @@ static int eqos_start(struct udevice *dev)
/* Enable Store and Forward mode for RX, since no jumbo frame */
setbits_le32(&eqos->mtl_regs->rxq0_operation_mode,
EQOS_MTL_RXQ0_OPERATION_MODE_RSF);
EQOS_MTL_RXQ0_OPERATION_MODE_RSF |
EQOS_MTL_RXQ0_OPERATION_MODE_FEP |
EQOS_MTL_RXQ0_OPERATION_MODE_FUP);
/* Transmit/Receive queue fifo size; use all RAM for 1 queue */
val = readl(&eqos->mac_regs->hw_feature1);
@ -1212,6 +1346,19 @@ static int eqos_start(struct udevice *dev)
eqos->config->config_mac <<
EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT);
clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0,
EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK <<
EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT,
0x2 <<
EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT);
/* Multicast and Broadcast Queue Enable */
setbits_le32(&eqos->mac_regs->unused_0a4,
0x00100000);
/* enable promise mode */
setbits_le32(&eqos->mac_regs->unused_004[1],
0x1);
/* Set TX flow control parameters */
/* Set Pause Time */
setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl,
@ -1289,7 +1436,11 @@ static int eqos_start(struct udevice *dev)
rx_desc->des0 = (u32)(ulong)(eqos->rx_dma_buf +
(i * EQOS_MAX_PACKET_SIZE));
rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
mb();
eqos->config->ops->eqos_flush_desc(rx_desc);
eqos->config->ops->eqos_inval_buffer(eqos->rx_dma_buf +
(i * EQOS_MAX_PACKET_SIZE),
EQOS_MAX_PACKET_SIZE);
}
writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress);
@ -1303,14 +1454,12 @@ static int eqos_start(struct udevice *dev)
&eqos->dma_regs->ch0_rxdesc_ring_length);
/* Enable everything */
setbits_le32(&eqos->mac_regs->configuration,
EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE);
setbits_le32(&eqos->dma_regs->ch0_tx_control,
EQOS_DMA_CH0_TX_CONTROL_ST);
setbits_le32(&eqos->dma_regs->ch0_rx_control,
EQOS_DMA_CH0_RX_CONTROL_SR);
setbits_le32(&eqos->mac_regs->configuration,
EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE);
/* TX tail pointer not written until we need to TX a packet */
/*
@ -1475,6 +1624,8 @@ static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length)
return -EINVAL;
}
eqos->config->ops->eqos_inval_buffer(packet, length);
rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]);
rx_desc->des0 = 0;
@ -1751,17 +1902,52 @@ static phy_interface_t eqos_get_interface_tegra186(struct udevice *dev)
return PHY_INTERFACE_MODE_MII;
}
static int eqos_probe_resources_imx(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
phy_interface_t interface;
debug("%s(dev=%p):\n", __func__, dev);
interface = eqos->config->interface(dev);
if (interface == PHY_INTERFACE_MODE_NONE) {
pr_err("Invalid PHY interface\n");
return -EINVAL;
}
debug("%s: OK\n", __func__);
return 0;
}
static phy_interface_t eqos_get_interface_imx(struct udevice *dev)
{
const char *phy_mode;
phy_interface_t interface = PHY_INTERFACE_MODE_NONE;
debug("%s(dev=%p):\n", __func__, dev);
phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
NULL);
if (phy_mode)
interface = phy_get_interface_by_name(phy_mode);
return interface;
}
static int eqos_remove_resources_tegra186(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
debug("%s(dev=%p):\n", __func__, dev);
#ifdef CONFIG_CLK
clk_free(&eqos->clk_tx);
clk_free(&eqos->clk_ptp_ref);
clk_free(&eqos->clk_rx);
clk_free(&eqos->clk_slave_bus);
clk_free(&eqos->clk_master_bus);
#endif
dm_gpio_free(dev, &eqos->phy_reset_gpio);
reset_free(&eqos->reset_ctl);
@ -1771,6 +1957,7 @@ static int eqos_remove_resources_tegra186(struct udevice *dev)
static int eqos_remove_resources_stm32(struct udevice *dev)
{
#ifdef CONFIG_CLK
struct eqos_priv *eqos = dev_get_priv(dev);
debug("%s(dev=%p):\n", __func__, dev);
@ -1780,6 +1967,7 @@ static int eqos_remove_resources_stm32(struct udevice *dev)
clk_free(&eqos->clk_master_bus);
if (clk_valid(&eqos->clk_ck))
clk_free(&eqos->clk_ck);
#endif
if (dm_gpio_is_valid(&eqos->phy_reset_gpio))
dm_gpio_free(dev, &eqos->phy_reset_gpio);
@ -1788,6 +1976,11 @@ static int eqos_remove_resources_stm32(struct udevice *dev)
return 0;
}
static int eqos_remove_resources_imx(struct udevice *dev)
{
return 0;
}
static int eqos_probe(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
@ -1820,23 +2013,32 @@ static int eqos_probe(struct udevice *dev)
goto err_remove_resources_core;
}
eqos->mii = mdio_alloc();
#ifdef CONFIG_DM_ETH_PHY
eqos->mii = eth_phy_get_mdio_bus(dev);
#endif
if (!eqos->mii) {
pr_err("mdio_alloc() failed");
ret = -ENOMEM;
goto err_remove_resources_tegra;
}
eqos->mii->read = eqos_mdio_read;
eqos->mii->write = eqos_mdio_write;
eqos->mii->priv = eqos;
strcpy(eqos->mii->name, dev->name);
eqos->mii = mdio_alloc();
if (!eqos->mii) {
pr_err("mdio_alloc() failed");
ret = -ENOMEM;
goto err_remove_resources_tegra;
}
eqos->mii->read = eqos_mdio_read;
eqos->mii->write = eqos_mdio_write;
eqos->mii->priv = eqos;
strcpy(eqos->mii->name, dev->name);
ret = mdio_register(eqos->mii);
if (ret < 0) {
pr_err("mdio_register() failed: %d", ret);
goto err_free_mdio;
ret = mdio_register(eqos->mii);
if (ret < 0) {
pr_err("mdio_register() failed: %d", ret);
goto err_free_mdio;
}
}
#ifdef CONFIG_DM_ETH_PHY
eth_phy_set_mdio_bus(dev, eqos->mii);
#endif
debug("%s: OK\n", __func__);
return 0;
@ -1874,6 +2076,7 @@ static const struct eth_ops eqos_ops = {
.recv = eqos_recv,
.free_pkt = eqos_free_pkt,
.write_hwaddr = eqos_write_hwaddr,
.read_rom_hwaddr = eqos_read_rom_hwaddr,
};
static struct eqos_ops eqos_tegra186_ops = {
@ -1904,10 +2107,10 @@ static const struct eqos_config eqos_tegra186_config = {
};
static struct eqos_ops eqos_stm32_ops = {
.eqos_inval_desc = eqos_inval_desc_stm32,
.eqos_flush_desc = eqos_flush_desc_stm32,
.eqos_inval_buffer = eqos_inval_buffer_stm32,
.eqos_flush_buffer = eqos_flush_buffer_stm32,
.eqos_inval_desc = eqos_inval_desc_generic,
.eqos_flush_desc = eqos_flush_desc_generic,
.eqos_inval_buffer = eqos_inval_buffer_generic,
.eqos_flush_buffer = eqos_flush_buffer_generic,
.eqos_probe_resources = eqos_probe_resources_stm32,
.eqos_remove_resources = eqos_remove_resources_stm32,
.eqos_stop_resets = eqos_stop_resets_stm32,
@ -1930,6 +2133,33 @@ static const struct eqos_config eqos_stm32_config = {
.ops = &eqos_stm32_ops
};
static struct eqos_ops eqos_imx_ops = {
.eqos_inval_desc = eqos_inval_desc_generic,
.eqos_flush_desc = eqos_flush_desc_generic,
.eqos_inval_buffer = eqos_inval_buffer_generic,
.eqos_flush_buffer = eqos_flush_buffer_generic,
.eqos_probe_resources = eqos_probe_resources_imx,
.eqos_remove_resources = eqos_remove_resources_imx,
.eqos_stop_resets = eqos_stop_resets_imx,
.eqos_start_resets = eqos_start_resets_imx,
.eqos_stop_clks = eqos_stop_clks_imx,
.eqos_start_clks = eqos_start_clks_imx,
.eqos_calibrate_pads = eqos_calibrate_pads_imx,
.eqos_disable_calibration = eqos_disable_calibration_imx,
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_imx,
.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_imx
};
struct eqos_config eqos_imx_config = {
.reg_access_always_ok = false,
.mdio_wait = 10000,
.swr_wait = 50,
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
.interface = eqos_get_interface_imx,
.ops = &eqos_imx_ops
};
static const struct udevice_id eqos_ids[] = {
{
.compatible = "nvidia,tegra186-eqos",
@ -1939,6 +2169,10 @@ static const struct udevice_id eqos_ids[] = {
.compatible = "snps,dwmac-4.20a",
.data = (ulong)&eqos_stm32_config
},
{
.compatible = "fsl,imx-eqos",
.data = (ulong)&eqos_imx_config
},
{ }
};
@ -1946,7 +2180,7 @@ static const struct udevice_id eqos_ids[] = {
U_BOOT_DRIVER(eth_eqos) = {
.name = "eth_eqos",
.id = UCLASS_ETH,
.of_match = eqos_ids,
.of_match = of_match_ptr(eqos_ids),
.probe = eqos_probe,
.remove = eqos_remove,
.ops = &eqos_ops,

View file

@ -0,0 +1,122 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2020 NXP
*/
#include <common.h>
#include <dm.h>
#include <net.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
#include <dm/lists.h>
struct eth_phy_device_priv {
struct mii_dev *mdio_bus;
};
int eth_phy_binds_nodes(struct udevice *eth_dev)
{
ofnode mdio_node, phy_node;
const char *node_name;
int ret;
mdio_node = dev_read_subnode(eth_dev, "mdio");
if (!ofnode_valid(mdio_node)) {
debug("%s: %s mdio subnode not found!", __func__,
eth_dev->name);
return -ENXIO;
}
ofnode_for_each_subnode(phy_node, mdio_node) {
node_name = ofnode_get_name(phy_node);
debug("* Found child node: '%s'\n", node_name);
ret = device_bind_driver_to_node(eth_dev,
"eth_phy_generic_drv",
node_name, phy_node, NULL);
if (ret) {
debug(" - Eth phy binding error: %d\n", ret);
continue;
}
debug(" - bound phy device: '%s'\n", node_name);
}
return 0;
}
int eth_phy_set_mdio_bus(struct udevice *eth_dev, struct mii_dev *mdio_bus)
{
struct udevice *dev;
struct eth_phy_device_priv *uc_priv;
for (uclass_first_device(UCLASS_ETH_PHY, &dev); dev;
uclass_next_device(&dev)) {
if (dev->parent == eth_dev) {
uc_priv = (struct eth_phy_device_priv *)(dev->uclass_priv);
if (!uc_priv->mdio_bus)
uc_priv->mdio_bus = mdio_bus;
}
}
return 0;
}
struct mii_dev *eth_phy_get_mdio_bus(struct udevice *eth_dev)
{
int ret;
struct udevice *phy_dev;
struct eth_phy_device_priv *uc_priv;
/* Will probe the parent of phy device, then phy device */
ret = uclass_get_device_by_phandle(UCLASS_ETH_PHY, eth_dev,
"phy-handle", &phy_dev);
if (!ret) {
if (eth_dev != phy_dev->parent) {
/*
* phy_dev is shared and controlled by
* other eth controller
*/
uc_priv = (struct eth_phy_device_priv *)(phy_dev->uclass_priv);
if (uc_priv->mdio_bus)
printf("Get shared mii bus on %s\n", eth_dev->name);
else
printf("Can't get shared mii bus on %s\n", eth_dev->name);
return uc_priv->mdio_bus;
}
} else {
printf("FEC: can't find phy-handle\n");
}
return NULL;
}
int eth_phy_get_addr(struct udevice *dev)
{
struct ofnode_phandle_args phandle_args;
int reg;
if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
&phandle_args)) {
debug("Failed to find phy-handle");
return -ENODEV;
}
reg = ofnode_read_u32_default(phandle_args.node, "reg", 0);
return reg;
}
UCLASS_DRIVER(eth_phy_generic) = {
.id = UCLASS_ETH_PHY,
.name = "eth_phy_generic",
.per_device_auto_alloc_size = sizeof(struct eth_phy_device_priv),
};
U_BOOT_DRIVER(eth_phy_generic_drv) = {
.name = "eth_phy_generic_drv",
.id = UCLASS_ETH_PHY,
};

View file

@ -28,6 +28,7 @@
#include <asm-generic/gpio.h>
#include "fec_mxc.h"
#include <eth_phy.h>
DECLARE_GLOBAL_DATA_PTR;
@ -1204,6 +1205,13 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
#endif
int ret;
if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) {
if (enet_fused((ulong)addr)) {
printf("SoC fuse indicates Ethernet@0x%x is unavailable.\n", addr);
return -ENODEV;
}
}
#ifdef CONFIG_FEC_MXC_MDIO_BASE
/*
* The i.MX28 has two ethernet interfaces, but they are not equal.
@ -1342,6 +1350,13 @@ static int fecmxc_probe(struct udevice *dev)
uint32_t start;
int ret;
if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) {
if (enet_fused((ulong)priv->eth)) {
printf("SoC fuse indicates Ethernet@0x%lx is unavailable.\n", (ulong)priv->eth);
return -ENODEV;
}
}
if (IS_ENABLED(CONFIG_IMX8)) {
ret = clk_get_by_name(dev, "ipg", &priv->ipg_clk);
if (ret < 0) {
@ -1430,16 +1445,27 @@ static int fecmxc_probe(struct udevice *dev)
fec_reg_setup(priv);
priv->dev_id = dev->seq;
#ifdef CONFIG_FEC_MXC_MDIO_BASE
bus = fec_get_miibus((ulong)CONFIG_FEC_MXC_MDIO_BASE, dev->seq);
#else
bus = fec_get_miibus((ulong)priv->eth, dev->seq);
#ifdef CONFIG_DM_ETH_PHY
bus = eth_phy_get_mdio_bus(dev);
#endif
if (!bus) {
#ifdef CONFIG_FEC_MXC_MDIO_BASE
bus = fec_get_miibus((ulong)CONFIG_FEC_MXC_MDIO_BASE, dev->seq);
#else
bus = fec_get_miibus((ulong)priv->eth, dev->seq);
#endif
}
if (!bus) {
ret = -ENOMEM;
goto err_mii;
}
#ifdef CONFIG_DM_ETH_PHY
eth_phy_set_mdio_bus(dev, bus);
#endif
priv->bus = bus;
priv->interface = pdata->phy_interface;
switch (priv->interface) {

View file

@ -273,8 +273,6 @@ struct fec_priv {
u32 clk_rate;
};
void imx_get_mac_from_fuse(int dev_id, unsigned char *mac);
/**
* @brief Numbers of buffer descriptors for receiving
*

View file

@ -56,6 +56,7 @@
#define MIIM_RTL8211F_PAGE_SELECT 0x1f
#define MIIM_RTL8211F_TX_DELAY 0x100
#define MIIM_RTL8211F_RX_DELAY 0x8
#define MIIM_RTL8211F_LCR 0x10
static int rtl8211f_phy_extread(struct phy_device *phydev, int addr,
@ -183,6 +184,16 @@ static int rtl8211f_config(struct phy_device *phydev)
reg &= ~MIIM_RTL8211F_TX_DELAY;
phy_write(phydev, MDIO_DEVAD_NONE, 0x11, reg);
/* enable RX-delay for rgmii-id and rgmii-rxid, otherwise disable it */
reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x15);
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
reg |= MIIM_RTL8211F_RX_DELAY;
else
reg &= ~MIIM_RTL8211F_RX_DELAY;
phy_write(phydev, MDIO_DEVAD_NONE, 0x15, reg);
/* restore to default page 0 */
phy_write(phydev, MDIO_DEVAD_NONE,
MIIM_RTL8211F_PAGE_SELECT, 0x0);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018 NXP
* Copyright 2018-2019 NXP
*/
#include <common.h>
@ -29,6 +29,11 @@ static int imx_pinconf_scu_set(struct imx_pinctrl_soc_info *info, u32 pad,
* to handle that in scfw, so config it in pad conf func
*/
if (!sc_rm_is_pad_owned(-1, pad)) {
debug("Pad[%u] is not owned by curr partition\n", pad);
return -EPERM;
}
val |= PADRING_IFMUX_EN_MASK;
val |= PADRING_GP_EN_MASK;
val |= (mux << PADRING_IFMUX_SHIFT) & PADRING_IFMUX_MASK;
@ -57,7 +62,7 @@ int imx_pinctrl_scu_conf_pins(struct imx_pinctrl_soc_info *info, u32 *pin_data,
config_val = pin_data[j++];
ret = imx_pinconf_scu_set(info, pin_id, mux, config_val);
if (ret)
if (ret && ret != -EPERM)
printf("Set pin %d, mux %d, val %d, error\n", pin_id,
mux, config_val);
}

View file

@ -11,6 +11,7 @@
#include <asm/arch/power-domain.h>
#include <dm/device-internal.h>
#include <dm/device.h>
#include <dm/uclass-internal.h>
#include <asm/arch/sci/sci.h>
DECLARE_GLOBAL_DATA_PTR;
@ -19,6 +20,68 @@ struct imx8_power_domain_priv {
bool state_on;
};
static bool check_device_power_off(struct udevice *dev,
const char *permanent_on_devices[],
int size)
{
int i;
for (i = 0; i < size; i++) {
if (!strcmp(dev->name, permanent_on_devices[i]))
return false;
}
return true;
}
void imx8_power_off_pd_devices(const char *permanent_on_devices[], int size)
{
struct udevice *dev;
struct power_domain pd;
for (uclass_find_first_device(UCLASS_POWER_DOMAIN, &dev); dev;
uclass_find_next_device(&dev)) {
if (!device_active(dev))
continue;
/*
* Power off active pd devices except the permanent
* power on devices
*/
if (check_device_power_off(dev, permanent_on_devices, size)) {
pd.dev = dev;
power_domain_off(&pd);
}
}
}
int imx8_power_domain_lookup_name(const char *name,
struct power_domain *power_domain)
{
struct udevice *dev;
struct power_domain_ops *ops;
int ret;
debug("%s(power_domain=%p name=%s)\n", __func__, power_domain, name);
ret = uclass_get_device_by_name(UCLASS_POWER_DOMAIN, name, &dev);
if (ret) {
printf("%s fail: %s, ret = %d\n", __func__, name, ret);
return ret;
}
ops = (struct power_domain_ops *)dev->driver->ops;
power_domain->dev = dev;
ret = ops->request(power_domain);
if (ret) {
debug("ops->request() failed: %d\n", ret);
return ret;
}
debug("%s ok: %s\n", __func__, dev->name);
return 0;
}
static int imx8_power_domain_request(struct power_domain *power_domain)
{
debug("%s(power_domain=%p)\n", __func__, power_domain);
@ -62,7 +125,10 @@ static int imx8_power_domain_on(struct power_domain *power_domain)
if (ppriv->state_on)
return 0;
if (pdata->resource_id != SC_R_LAST) {
if (pdata->resource_id != SC_R_NONE) {
if (!sc_rm_is_resource_owned(-1, pdata->resource_id))
printf("%s [%d] not owned by curr partition\n", dev->name, pdata->resource_id);
ret = sc_pm_set_resource_power_mode(-1, pdata->resource_id,
SC_PM_PW_MODE_ON);
if (ret) {
@ -108,14 +174,14 @@ static int imx8_power_domain_off_node(struct power_domain *power_domain)
}
}
if (pdata->resource_id != SC_R_LAST) {
if (!sc_rm_is_resource_owned(-1, pdata->resource_id)) {
printf("%s not owned by curr partition\n", dev->name);
return 0;
}
if (pdata->resource_id != SC_R_NONE) {
ret = sc_pm_set_resource_power_mode(-1, pdata->resource_id,
SC_PM_PW_MODE_OFF);
if (ret) {
if (!sc_rm_is_resource_owned(-1, pdata->resource_id)) {
printf("%s not owned by curr partition %d\n", dev->name, pdata->resource_id);
return 0;
}
printf("Error: %s Power off failed! (error = %d)\n",
dev->name, ret);
return -EIO;
@ -171,7 +237,7 @@ static int imx8_power_domain_off_parentnodes(struct power_domain *power_domain)
}
/* power off parent */
if (pdata->resource_id != SC_R_LAST) {
if (pdata->resource_id != SC_R_NONE) {
ret = sc_pm_set_resource_power_mode(-1,
pdata->resource_id,
SC_PM_PW_MODE_OFF);
@ -313,4 +379,5 @@ U_BOOT_DRIVER(imx8_power_domain) = {
.platdata_auto_alloc_size = sizeof(struct imx8_power_domain_platdata),
.priv_auto_alloc_size = sizeof(struct imx8_power_domain_priv),
.ops = &imx8_power_domain_ops,
.flags = DM_FLAG_DEFAULT_PD_CTRL_OFF,
};

View file

@ -26,6 +26,15 @@ config IMX_SCU_THERMAL
boot is hold to the cool device to throttle CPUs when the passive
trip is crossed
config IMX_TMU
bool "Thermal Management Unit driver for NXP i.MX8M"
depends on ARCH_IMX8M
help
Support for Temperature sensors on NXP i.MX8M.
It supports one critical trip point and one passive trip point.
The boot is hold to the cool device to throttle CPUs when the
passive trip is crossed
config TI_DRA7_THERMAL
bool "Temperature sensor driver for TI dra7xx SOCs"
help

View file

@ -7,3 +7,4 @@ obj-$(CONFIG_DM_THERMAL) += thermal-uclass.o
obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
obj-$(CONFIG_IMX_SCU_THERMAL) += imx_scu_thermal.o
obj-$(CONFIG_TI_DRA7_THERMAL) += ti-bandgap.o
obj-$(CONFIG_IMX_TMU) += imx_tmu.o

View file

@ -179,12 +179,20 @@ static int imx_sc_thermal_ofdata_to_platdata(struct udevice *dev)
return 0;
}
static const sc_rsrc_t imx8qm_sensor_rsrc[] = {
SC_R_A53, SC_R_A72, SC_R_GPU_0_PID0, SC_R_GPU_1_PID0,
SC_R_DRC_0, SC_R_DRC_1, SC_R_VPU_PID0, SC_R_PMIC_0,
SC_R_PMIC_1, SC_R_PMIC_2,
};
static const sc_rsrc_t imx8qxp_sensor_rsrc[] = {
SC_R_SYSTEM, SC_R_DRC_0, SC_R_PMIC_0,
SC_R_PMIC_1, SC_R_PMIC_2,
};
static const struct udevice_id imx_sc_thermal_ids[] = {
{ .compatible = "nxp,imx8qm-sc-tsens", .data =
(ulong)&imx8qm_sensor_rsrc, },
{ .compatible = "nxp,imx8qxp-sc-tsens", .data =
(ulong)&imx8qxp_sensor_rsrc, },
{ }

467
drivers/thermal/imx_tmu.c Normal file
View file

@ -0,0 +1,467 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2017~2020 NXP
*
*/
#include <config.h>
#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/sys_proto.h>
#include <dm.h>
#include <dm/device-internal.h>
#include <dm/device.h>
#include <errno.h>
#include <fuse.h>
#include <malloc.h>
#include <thermal.h>
DECLARE_GLOBAL_DATA_PTR;
#define SITES_MAX 16
#define FLAGS_VER2 0x1
#define FLAGS_VER3 0x2
#define TMR_DISABLE 0x0
#define TMR_ME 0x80000000
#define TMR_ALPF 0x0c000000
#define TMTMIR_DEFAULT 0x00000002
#define TIER_DISABLE 0x0
#define TER_EN 0x80000000
#define TER_ADC_PD 0x40000000
#define TER_ALPF 0x3
/*
* i.MX TMU Registers
*/
struct imx_tmu_site_regs {
u32 tritsr; /* Immediate Temperature Site Register */
u32 tratsr; /* Average Temperature Site Register */
u8 res0[0x8];
};
struct imx_tmu_regs {
u32 tmr; /* Mode Register */
u32 tsr; /* Status Register */
u32 tmtmir; /* Temperature measurement interval Register */
u8 res0[0x14];
u32 tier; /* Interrupt Enable Register */
u32 tidr; /* Interrupt Detect Register */
u32 tiscr; /* Interrupt Site Capture Register */
u32 ticscr; /* Interrupt Critical Site Capture Register */
u8 res1[0x10];
u32 tmhtcrh; /* High Temperature Capture Register */
u32 tmhtcrl; /* Low Temperature Capture Register */
u8 res2[0x8];
u32 tmhtitr; /* High Temperature Immediate Threshold */
u32 tmhtatr; /* High Temperature Average Threshold */
u32 tmhtactr; /* High Temperature Average Crit Threshold */
u8 res3[0x24];
u32 ttcfgr; /* Temperature Configuration Register */
u32 tscfgr; /* Sensor Configuration Register */
u8 res4[0x78];
struct imx_tmu_site_regs site[SITES_MAX];
u8 res5[0x9f8];
u32 ipbrr0; /* IP Block Revision Register 0 */
u32 ipbrr1; /* IP Block Revision Register 1 */
u8 res6[0x310];
u32 ttr0cr; /* Temperature Range 0 Control Register */
u32 ttr1cr; /* Temperature Range 1 Control Register */
u32 ttr2cr; /* Temperature Range 2 Control Register */
u32 ttr3cr; /* Temperature Range 3 Control Register */
};
struct imx_tmu_regs_v2 {
u32 ter; /* TMU enable Register */
u32 tsr; /* Status Register */
u32 tier; /* Interrupt enable register */
u32 tidr; /* Interrupt detect register */
u32 tmhtitr; /* Monitor high temperature immediate threshold register */
u32 tmhtatr; /* Monitor high temperature average threshold register */
u32 tmhtactr; /* TMU monitor high temperature average critical threshold register */
u32 tscr; /* Sensor value capture register */
u32 tritsr; /* Report immediate temperature site register 0 */
u32 tratsr; /* Report average temperature site register 0 */
u32 tasr; /* Amplifier setting register */
u32 ttmc; /* Test MUX control */
u32 tcaliv;
};
struct imx_tmu_regs_v3 {
u32 ter; /* TMU enable Register */
u32 tps; /* Status Register */
u32 tier; /* Interrupt enable register */
u32 tidr; /* Interrupt detect register */
u32 tmhtitr; /* Monitor high temperature immediate threshold register */
u32 tmhtatr; /* Monitor high temperature average threshold register */
u32 tmhtactr; /* TMU monitor high temperature average critical threshold register */
u32 tscr; /* Sensor value capture register */
u32 tritsr; /* Report immediate temperature site register 0 */
u32 tratsr; /* Report average temperature site register 0 */
u32 tasr; /* Amplifier setting register */
u32 ttmc; /* Test MUX control */
u32 tcaliv0;
u32 tcaliv1;
u32 tcaliv_m40;
u32 trim;
};
union tmu_regs {
struct imx_tmu_regs regs_v1;
struct imx_tmu_regs_v2 regs_v2;
struct imx_tmu_regs_v3 regs_v3;
};
struct imx_tmu_plat {
int critical;
int alert;
int polling_delay;
int id;
bool zone_node;
union tmu_regs *regs;
};
static int read_temperature(struct udevice *dev, int *temp)
{
struct imx_tmu_plat *pdata = dev_get_platdata(dev);
ulong drv_data = dev_get_driver_data(dev);
u32 val;
u32 retry = 10;
u32 valid = 0;
do {
mdelay(100);
retry--;
if (drv_data & FLAGS_VER3) {
val = readl(&pdata->regs->regs_v3.tritsr);
valid = val & (1 << (30 + pdata->id));
} else if (drv_data & FLAGS_VER2) {
val = readl(&pdata->regs->regs_v2.tritsr);
/*
* Check if TEMP is in valid range, the V bit in TRITSR
* only reflects the RAW uncalibrated data
*/
valid = ((val & 0xff) < 10 || (val & 0xff) > 125) ? 0 : 1;
} else {
val = readl(&pdata->regs->regs_v1.site[pdata->id].tritsr);
valid = val & 0x80000000;
}
} while (!valid && retry > 0);
if (retry > 0) {
if (drv_data & FLAGS_VER3) {
val = (val >> (pdata->id * 16)) & 0xff;
if (val & 0x80) /* Negative */
val = (~(val & 0x7f) + 1);
*temp = val;
if (*temp < -40 || *temp > 125) /* Check the range */
return -EINVAL;
*temp *= 1000;
} else {
*temp = (val & 0xff) * 1000;
}
} else {
return -EINVAL;
}
return 0;
}
int imx_tmu_get_temp(struct udevice *dev, int *temp)
{
struct imx_tmu_plat *pdata = dev_get_platdata(dev);
int cpu_tmp = 0;
int ret;
ret = read_temperature(dev, &cpu_tmp);
if (ret)
return ret;
while (cpu_tmp >= pdata->alert) {
printf("CPU Temperature (%dC) has beyond alert (%dC), close to critical (%dC)", cpu_tmp, pdata->alert, pdata->critical);
puts(" waiting...\n");
mdelay(pdata->polling_delay);
ret = read_temperature(dev, &cpu_tmp);
if (ret)
return ret;
}
*temp = cpu_tmp / 1000;
return 0;
}
static const struct dm_thermal_ops imx_tmu_ops = {
.get_temp = imx_tmu_get_temp,
};
static int imx_tmu_calibration(struct udevice *dev)
{
int i, val, len, ret;
u32 range[4];
const fdt32_t *calibration;
struct imx_tmu_plat *pdata = dev_get_platdata(dev);
ulong drv_data = dev_get_driver_data(dev);
debug("%s\n", __func__);
if (drv_data & (FLAGS_VER2 | FLAGS_VER3))
return 0;
ret = dev_read_u32_array(dev, "fsl,tmu-range", range, 4);
if (ret) {
printf("TMU: missing calibration range, ret = %d.\n", ret);
return ret;
}
/* Init temperature range registers */
writel(range[0], &pdata->regs->regs_v1.ttr0cr);
writel(range[1], &pdata->regs->regs_v1.ttr1cr);
writel(range[2], &pdata->regs->regs_v1.ttr2cr);
writel(range[3], &pdata->regs->regs_v1.ttr3cr);
calibration = dev_read_prop(dev, "fsl,tmu-calibration", &len);
if (!calibration || len % 8) {
printf("TMU: invalid calibration data.\n");
return -ENODEV;
}
for (i = 0; i < len; i += 8, calibration += 2) {
val = fdt32_to_cpu(*calibration);
writel(val, &pdata->regs->regs_v1.ttcfgr);
val = fdt32_to_cpu(*(calibration + 1));
writel(val, &pdata->regs->regs_v1.tscfgr);
}
return 0;
}
void __weak imx_tmu_arch_init(void *reg_base)
{
}
static void imx_tmu_init(struct udevice *dev)
{
struct imx_tmu_plat *pdata = dev_get_platdata(dev);
ulong drv_data = dev_get_driver_data(dev);
debug("%s\n", __func__);
if (drv_data & FLAGS_VER3) {
/* Disable monitoring */
writel(0x0, &pdata->regs->regs_v3.ter);
/* Disable interrupt, using polling instead */
writel(0x0, &pdata->regs->regs_v3.tier);
} else if (drv_data & FLAGS_VER2) {
/* Disable monitoring */
writel(0x0, &pdata->regs->regs_v2.ter);
/* Disable interrupt, using polling instead */
writel(0x0, &pdata->regs->regs_v2.tier);
} else {
/* Disable monitoring */
writel(TMR_DISABLE, &pdata->regs->regs_v1.tmr);
/* Disable interrupt, using polling instead */
writel(TIER_DISABLE, &pdata->regs->regs_v1.tier);
/* Set update_interval */
writel(TMTMIR_DEFAULT, &pdata->regs->regs_v1.tmtmir);
}
imx_tmu_arch_init((void *)pdata->regs);
}
static int imx_tmu_enable_msite(struct udevice *dev)
{
struct imx_tmu_plat *pdata = dev_get_platdata(dev);
ulong drv_data = dev_get_driver_data(dev);
u32 reg;
debug("%s\n", __func__);
if (!pdata->regs)
return -EIO;
if (drv_data & FLAGS_VER3) {
reg = readl(&pdata->regs->regs_v3.ter);
reg &= ~TER_EN;
writel(reg, &pdata->regs->regs_v3.ter);
writel(pdata->id << 30, &pdata->regs->regs_v3.tps);
reg &= ~TER_ALPF;
reg |= 0x1;
reg &= ~TER_ADC_PD;
writel(reg, &pdata->regs->regs_v3.ter);
/* Enable monitor */
reg |= TER_EN;
writel(reg, &pdata->regs->regs_v3.ter);
} else if (drv_data & FLAGS_VER2) {
reg = readl(&pdata->regs->regs_v2.ter);
reg &= ~TER_EN;
writel(reg, &pdata->regs->regs_v2.ter);
reg &= ~TER_ALPF;
reg |= 0x1;
writel(reg, &pdata->regs->regs_v2.ter);
/* Enable monitor */
reg |= TER_EN;
writel(reg, &pdata->regs->regs_v2.ter);
} else {
/* Clear the ME before setting MSITE and ALPF*/
reg = readl(&pdata->regs->regs_v1.tmr);
reg &= ~TMR_ME;
writel(reg, &pdata->regs->regs_v1.tmr);
reg |= 1 << (15 - pdata->id);
reg |= TMR_ALPF;
writel(reg, &pdata->regs->regs_v1.tmr);
/* Enable ME */
reg |= TMR_ME;
writel(reg, &pdata->regs->regs_v1.tmr);
}
return 0;
}
static int imx_tmu_bind(struct udevice *dev)
{
struct imx_tmu_plat *pdata = dev_get_platdata(dev);
int ret;
ofnode node, offset;
const char *name;
const void *prop;
debug("%s dev name %s\n", __func__, dev->name);
prop = dev_read_prop(dev, "compatible", NULL);
if (!prop)
return 0;
pdata->zone_node = 1;
node = ofnode_path("/thermal-zones");
ofnode_for_each_subnode(offset, node) {
/* Bind the subnode to this driver */
name = ofnode_get_name(offset);
ret = device_bind_with_driver_data(dev, dev->driver, name,
dev->driver_data, offset,
NULL);
if (ret)
printf("Error binding driver '%s': %d\n",
dev->driver->name, ret);
}
return 0;
}
static int imx_tmu_parse_fdt(struct udevice *dev)
{
struct imx_tmu_plat *pdata = dev_get_platdata(dev), *p_parent_data;
struct ofnode_phandle_args args;
ofnode trips_np;
int ret;
debug("%s dev name %s\n", __func__, dev->name);
if (pdata->zone_node) {
pdata->regs = (union tmu_regs *)dev_read_addr_ptr(dev);
if (!pdata->regs)
return -EINVAL;
return 0;
}
p_parent_data = dev_get_platdata(dev->parent);
if (p_parent_data->zone_node)
pdata->regs = p_parent_data->regs;
ret = dev_read_phandle_with_args(dev, "thermal-sensors",
"#thermal-sensor-cells",
0, 0, &args);
if (ret)
return ret;
if (!ofnode_equal(args.node, dev_ofnode(dev->parent)))
return -EFAULT;
if (args.args_count >= 1)
pdata->id = args.args[0];
else
pdata->id = 0;
debug("args.args_count %d, id %d\n", args.args_count, pdata->id);
pdata->polling_delay = dev_read_u32_default(dev, "polling-delay", 1000);
trips_np = ofnode_path("/thermal-zones/cpu-thermal/trips");
ofnode_for_each_subnode(trips_np, trips_np) {
const char *type;
type = ofnode_get_property(trips_np, "type", NULL);
if (!type)
continue;
if (!strcmp(type, "critical"))
pdata->critical = ofnode_read_u32_default(trips_np, "temperature", 85);
else if (strcmp(type, "passive") == 0)
pdata->alert = ofnode_read_u32_default(trips_np, "temperature", 80);
else
continue;
}
debug("id %d polling_delay %d, critical %d, alert %d\n",
pdata->id, pdata->polling_delay, pdata->critical, pdata->alert);
return 0;
}
static int imx_tmu_probe(struct udevice *dev)
{
struct imx_tmu_plat *pdata = dev_get_platdata(dev);
int ret;
ret = imx_tmu_parse_fdt(dev);
if (ret) {
printf("Error in parsing TMU FDT %d\n", ret);
return ret;
}
if (pdata->zone_node) {
imx_tmu_init(dev);
imx_tmu_calibration(dev);
} else {
imx_tmu_enable_msite(dev);
}
return 0;
}
static const struct udevice_id imx_tmu_ids[] = {
{ .compatible = "fsl,imx8mq-tmu", },
{ .compatible = "fsl,imx8mm-tmu", .data = FLAGS_VER2, },
{ .compatible = "fsl,imx8mp-tmu", .data = FLAGS_VER3, },
{ }
};
U_BOOT_DRIVER(imx_tmu) = {
.name = "imx_tmu",
.id = UCLASS_THERMAL,
.ops = &imx_tmu_ops,
.of_match = imx_tmu_ids,
.bind = imx_tmu_bind,
.probe = imx_tmu_probe,
.platdata_auto_alloc_size = sizeof(struct imx_tmu_plat),
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -122,6 +122,10 @@ config USB_GADGET_VBUS_DRAW
This value will be used except for system-specific gadget
drivers that have more specific information.
config SDP_LOADADDR
hex "Default load address at SDP_WRITE and SDP_JUMP"
default 0
# Selected by UDC drivers that support high-speed operation.
config USB_GADGET_DUALSPEED
bool

View file

@ -276,7 +276,7 @@ static void sdp_rx_command_complete(struct usb_ep *ep, struct usb_request *req)
sdp->error_status = SDP_WRITE_FILE_COMPLETE;
sdp->state = SDP_STATE_RX_FILE_DATA;
sdp->dnl_address = be32_to_cpu(cmd->addr);
sdp->dnl_address = cmd->addr ? be32_to_cpu(cmd->addr) : CONFIG_SDP_LOADADDR;
sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt);
sdp->dnl_bytes = sdp->dnl_bytes_remaining;
sdp->next_state = SDP_STATE_IDLE;
@ -304,7 +304,7 @@ static void sdp_rx_command_complete(struct usb_ep *ep, struct usb_request *req)
sdp->always_send_status = false;
sdp->error_status = 0;
sdp->jmp_address = be32_to_cpu(cmd->addr);
sdp->jmp_address = cmd->addr ? be32_to_cpu(cmd->addr) : CONFIG_SDP_LOADADDR;
sdp->state = SDP_STATE_TX_SEC_CONF;
sdp->next_state = SDP_STATE_JUMP;
break;

View file

@ -380,6 +380,14 @@ int ehci_hcd_init(int index, enum usb_init_type init,
if (index > 3)
return -EINVAL;
if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) {
if (usb_fused((ulong)ehci)) {
printf("SoC fuse indicates USB@0x%lx is unavailable.\n",
(ulong)ehci);
return -ENODEV;
}
}
ret = ehci_mx6_common_init(ehci, index);
if (ret)
return ret;
@ -577,6 +585,14 @@ static int ehci_usb_probe(struct udevice *dev)
struct ehci_hcor *hcor;
int ret;
if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) {
if (usb_fused((ulong)ehci)) {
printf("SoC fuse indicates USB@0x%lx is unavailable.\n",
(ulong)ehci);
return -ENODEV;
}
}
priv->ehci = ehci;
priv->portnr = dev->seq;
priv->init_type = type;

View file

@ -0,0 +1,152 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2020 Compass Electronics Group, LLC
*/
#ifndef __IMX8MM_BEACON_H
#define __IMX8MM_BEACON_H
#include <linux/sizes.h>
#include <asm/arch/imx-regs.h>
#ifdef CONFIG_SECURE_BOOT
#define CONFIG_CSF_SIZE SZ_8K
#endif
#define CONFIG_SPL_MAX_SIZE (148 * 1024)
#define CONFIG_SYS_MONITOR_LEN SZ_512K
#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x300
#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 1
#define CONFIG_SYS_UBOOT_BASE \
(QSPI0_AMBA_BASE + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512)
#ifdef CONFIG_SPL_BUILD
#define CONFIG_SPL_STACK 0x920000
#define CONFIG_SPL_BSS_START_ADDR 0x910000
#define CONFIG_SPL_BSS_MAX_SIZE SZ_8K /* 8 KB */
#define CONFIG_SYS_SPL_MALLOC_START 0x42200000
#define CONFIG_SYS_SPL_MALLOC_SIZE SZ_512K /* 512 KB */
/* malloc f used before GD_FLG_FULL_MALLOC_INIT set */
#define CONFIG_MALLOC_F_ADDR 0x930000
/* For RAW image gives a error info not panic */
#define CONFIG_SPL_ABORT_ON_RAW_IMAGE
#endif
/* Initial environment variables */
#define CONFIG_EXTRA_ENV_SETTINGS \
"script=boot.scr\0" \
"image=Image\0" \
"console=ttymxc1,115200\0" \
"fdt_addr=0x43000000\0" \
"fdt_high=0xffffffffffffffff\0" \
"boot_fit=try\0" \
"fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \
"initrd_addr=0x43800000\0" \
"initrd_high=0xffffffffffffffff\0" \
"mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV) "\0" \
"mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \
"finduuid=part uuid mmc ${mmcdev}:2 uuid\0" \
"mmcautodetect=yes\0" \
"mmcargs=setenv bootargs console=${console},${baudrate}" \
" root=PARTUUID=${uuid} rootwait rw ${mtdparts} ${optargs}\0" \
"loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr}" \
" ${script};\0" \
"bootscript=echo Running bootscript from mmc ...; " \
"source\0" \
"loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \
"loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0" \
"mmcboot=echo Booting from mmc ...; " \
"run finduuid; " \
"run mmcargs; " \
"if run loadfdt; then " \
"booti ${loadaddr} - ${fdt_addr}; " \
"else " \
"echo WARN: Cannot load the DT; " \
"fi; " \
"netargs=setenv bootargs console=${console} " \
"root=/dev/nfs " \
"ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \
"netboot=echo Booting from net ...; " \
"run netargs; " \
"if test ${ip_dyn} = yes; then " \
"setenv get_cmd dhcp; " \
"else " \
"setenv get_cmd tftp; " \
"fi; " \
"${get_cmd} ${loadaddr} ${image}; " \
"if test ${boot_fit} = yes || test ${boot_fit} = try; then " \
"bootm ${loadaddr}; " \
"else " \
"if ${get_cmd} ${fdt_addr} ${fdt_file}; then " \
"booti ${loadaddr} - ${fdt_addr}; " \
"else " \
"echo WARN: Cannot load the DT; " \
"fi; " \
"fi;\0"
#define CONFIG_BOOTCOMMAND \
"mmc dev ${mmcdev}; if mmc rescan; then " \
"if run loadbootscript; then " \
"run bootscript; " \
"else " \
"if run loadimage; then " \
"run mmcboot; " \
"else run netboot; " \
"fi; " \
"fi; " \
"fi;"
/* Link Definitions */
#define CONFIG_LOADADDR 0x40480000
#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR
#define CONFIG_SYS_INIT_RAM_ADDR 0x40000000
#define CONFIG_SYS_INIT_RAM_SIZE 0x200000
#define CONFIG_SYS_INIT_SP_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
#define CONFIG_ENV_OVERWRITE
#define CONFIG_SYS_MMC_ENV_DEV 1 /* USDHC2 */
/* Size of malloc() pool */
#define CONFIG_SYS_MALLOC_LEN SZ_32M
#define CONFIG_SYS_SDRAM_BASE 0x40000000
#define PHYS_SDRAM 0x40000000
#define PHYS_SDRAM_SIZE 0x80000000 /* 2GB DDR */
#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + (PHYS_SDRAM_SIZE >> 1))
#define CONFIG_MXC_UART_BASE UART2_BASE_ADDR
/* Monitor Command Prompt */
#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
#define CONFIG_SYS_CBSIZE 2048
#define CONFIG_SYS_MAXARGS 64
#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \
sizeof(CONFIG_SYS_PROMPT) + 16)
/* USDHC */
#define CONFIG_SYS_FSL_USDHC_NUM 2
#define CONFIG_SYS_FSL_ESDHC_ADDR 0
#define CONFIG_SYS_MMC_IMG_LOAD_PART 1
/* I2C */
#define CONFIG_SYS_I2C_SPEED 100000
/* FEC*/
#define CONFIG_ETHPRIME "FEC"
#define CONFIG_FEC_XCV_TYPE RGMII
#define CONFIG_FEC_MXC_PHYADDR 0
#define FEC_QUIRK_ENET_MAC
#define IMX_FEC_BASE 0x30BE0000
#endif

View file

@ -70,7 +70,7 @@
"fdt_addr=0x83000000\0" \
"fdt_high=0xffffffffffffffff\0" \
"boot_fdt=try\0" \
"fdt_file=imx8qm-mek.dtb\0" \
"fdt_file=undefined\0" \
"initrd_addr=0x83800000\0" \
"initrd_high=0xffffffffffffffff\0" \
"mmcdev="__stringify(CONFIG_SYS_MMC_ENV_DEV)"\0" \

View file

@ -69,7 +69,7 @@
"fdt_addr=0x83000000\0" \
"fdt_high=0xffffffffffffffff\0" \
"boot_fdt=try\0" \
"fdt_file=imx8qxp-mek.dtb\0" \
"fdt_file=undefined\0" \
"initrd_addr=0x83800000\0" \
"initrd_high=0xffffffffffffffff\0" \
"mmcdev="__stringify(CONFIG_SYS_MMC_ENV_DEV)"\0" \

View file

@ -0,0 +1,199 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2018 NXP
*/
#ifndef __IMX8M_PICOPI_H
#define __IMX8M_PICOPI_H
#include <linux/sizes.h>
#include <asm/arch/imx-regs.h>
#define CONFIG_SPL_MAX_SIZE (124 * 1024)
#define CONFIG_SYS_MONITOR_LEN (512 * 1024)
#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x300
#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 1
#ifdef CONFIG_SPL_BUILD
/*#define CONFIG_ENABLE_DDR_TRAINING_DEBUG*/
#define CONFIG_SPL_WATCHDOG_SUPPORT
#define CONFIG_SPL_DRIVERS_MISC_SUPPORT
#define CONFIG_SPL_POWER_SUPPORT
#define CONFIG_SPL_I2C_SUPPORT
#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv8/u-boot-spl.lds"
#define CONFIG_SPL_STACK 0x187FF0
#define CONFIG_SPL_LIBCOMMON_SUPPORT
#define CONFIG_SPL_LIBGENERIC_SUPPORT
#define CONFIG_SPL_GPIO_SUPPORT
#define CONFIG_SPL_MMC_SUPPORT
#define CONFIG_SPL_BSS_START_ADDR 0x00180000
#define CONFIG_SPL_BSS_MAX_SIZE 0x2000 /* 8 KB */
#define CONFIG_SYS_SPL_MALLOC_START 0x42200000
#define CONFIG_SYS_SPL_MALLOC_SIZE 0x80000 /* 512 KB */
#define CONFIG_SYS_SPL_PTE_RAM_BASE 0x41580000
/* malloc f used before GD_FLG_FULL_MALLOC_INIT set */
#define CONFIG_MALLOC_F_ADDR 0x182000
/* For RAW image gives a error info not panic */
#define CONFIG_SPL_ABORT_ON_RAW_IMAGE
#undef CONFIG_DM_MMC
#undef CONFIG_DM_PMIC
#define CONFIG_SYS_I2C
#define CONFIG_SYS_I2C_MXC_I2C1 /* enable I2C bus 1 */
#define CONFIG_SYS_I2C_MXC_I2C2 /* enable I2C bus 2 */
#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */
#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
#define CONFIG_POWER
#define CONFIG_POWER_I2C
#endif
#define CONFIG_REMAKE_ELF
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_BOARD_LATE_INIT
#undef CONFIG_CMD_EXPORTENV
#undef CONFIG_CMD_IMPORTENV
#undef CONFIG_CMD_IMLS
#undef CONFIG_CMD_CRC32
/* ENET Config */
/* ENET1 */
#if defined(CONFIG_CMD_NET)
#define CONFIG_CMD_PING
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_MII
#define CONFIG_MII
#define CONFIG_ETHPRIME "FEC"
#define CONFIG_FEC_MXC
#define CONFIG_FEC_XCV_TYPE RGMII
#define CONFIG_FEC_MXC_PHYADDR 1
#define FEC_QUIRK_ENET_MAC
#define CONFIG_PHY_GIGE
#define IMX_FEC_BASE 0x30BE0000
#define CONFIG_PHYLIB
#define CONFIG_PHY_ATHEROS
#endif
/* Initial environment variables */
#define CONFIG_EXTRA_ENV_SETTINGS \
"script=boot.scr\0" \
"image=Image\0" \
"console=ttymxc0,115200\0" \
"fdt_addr=0x43000000\0" \
"fdt_high=0xffffffffffffffff\0" \
"fdt_file=imx8mq-pico-pi.dtb\0" \
"initrd_addr=0x43800000\0" \
"initrd_high=0xffffffffffffffff\0" \
"mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV) "\0" \
"mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \
"mmcroot=" CONFIG_MMCROOT " rootwait rw\0" \
"mmcautodetect=yes\0" \
"mmcargs=setenv bootargs console=${console} root=${mmcroot}\0 " \
"loadbootscript=" \
"fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
"bootscript=echo Running bootscript from mmc ...; source\0" \
"loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \
"loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0" \
"mmcboot=echo Booting from mmc ...; " \
"run mmcargs; " \
"echo wait for boot; " \
"fi;\0" \
"netargs=setenv bootargs console=${console} " \
"root=/dev/nfs " \
"ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \
"netboot=echo Booting from net ...; " \
"run netargs; " \
"if test ${ip_dyn} = yes; then " \
"setenv get_cmd dhcp; " \
"else " \
"setenv get_cmd tftp; " \
"fi; " \
"${get_cmd} ${loadaddr} ${image}; " \
"booti; "
#define CONFIG_BOOTCOMMAND \
"mmc dev ${mmcdev}; if mmc rescan; then " \
"if run loadbootscript; then " \
"run bootscript; " \
"else " \
"if run loadimage; then " \
"run mmcboot; " \
"else run netboot; " \
"fi; " \
"fi; " \
"else booti ${loadaddr} - ${fdt_addr}; fi"
/* Link Definitions */
#define CONFIG_LOADADDR 0x40480000
#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR
#define CONFIG_SYS_INIT_RAM_ADDR 0x40000000
#define CONFIG_SYS_INIT_RAM_SIZE 0x80000
#define CONFIG_SYS_INIT_SP_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
#define CONFIG_ENV_OVERWRITE
#define CONFIG_SYS_MMC_ENV_DEV 1 /* USDHC2 */
#define CONFIG_MMCROOT "/dev/mmcblk1p2" /* USDHC2 */
/* Size of malloc() pool */
#define CONFIG_SYS_MALLOC_LEN ((CONFIG_ENV_SIZE + (2 * 1024)) * 1024)
#define CONFIG_SYS_SDRAM_BASE 0x40000000
#define PHYS_SDRAM 0x40000000
#define PHYS_SDRAM_SIZE 0x80000000 /* 2 GiB DDR */
#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + \
(PHYS_SDRAM_SIZE >> 1))
#define CONFIG_BAUDRATE 115200
#define CONFIG_MXC_UART
#define CONFIG_MXC_UART_BASE UART1_BASE_ADDR
/* Monitor Command Prompt */
#define CONFIG_SYS_CBSIZE 1024
#define CONFIG_SYS_MAXARGS 64
#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \
sizeof(CONFIG_SYS_PROMPT) + 16)
#define CONFIG_IMX_BOOTAUX
#define CONFIG_CMD_MMC
#define CONFIG_SYS_FSL_USDHC_NUM 2
#define CONFIG_SYS_FSL_ESDHC_ADDR 0
#define CONFIG_SYS_MMC_IMG_LOAD_PART 1
#define CONFIG_MXC_GPIO
#define CONFIG_CMD_FUSE
/* I2C Configs */
#define CONFIG_SYS_I2C_SPEED 100000
#define CONFIG_OF_SYSTEM_SETUP
#ifndef CONFIG_SPL_BUILD
#define CONFIG_DM_PMIC
#endif
#define CONFIG_SYS_BOOTM_LEN SZ_128M
#endif

View file

@ -89,6 +89,15 @@ struct cpu_ops {
* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
*/
int (*get_vendor)(struct udevice *dev, char *buf, int size);
/**
* is_current() - Check if the CPU that U-Boot is currently running from
*
* @dev: Device to check (UCLASS_CPU)
* @return 1 if the CPU that U-Boot is currently running from, 0
* if not.
*/
int (*is_current)(struct udevice *dev);
};
#define cpu_get_ops(dev) ((struct cpu_ops *)(dev)->driver->ops)
@ -137,4 +146,18 @@ int cpu_get_vendor(struct udevice *dev, char *buf, int size);
*/
int cpu_probe_all(void);
/**
* cpu_is_current() - Check if the CPU that U-Boot is currently running from
*
* Return: 1 if yes, - 0 if not
*/
int cpu_is_current(struct udevice *cpu);
/**
* cpu_get_current_dev() - Get CPU udevice for current CPU
*
* Return: udevice if OK, - NULL on error
*/
struct udevice *cpu_get_current_dev(void);
#endif

View file

@ -47,6 +47,7 @@ enum uclass_id {
UCLASS_DMA, /* Direct Memory Access */
UCLASS_EFI, /* EFI managed devices */
UCLASS_ETH, /* Ethernet device */
UCLASS_ETH_PHY, /* Ethernet PHY device */
UCLASS_FIRMWARE, /* Firmware */
UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */
UCLASS_GPIO, /* Bank of general-purpose I/O pins */

View file

@ -553,5 +553,6 @@
#define SC_R_VPU_ENC_1 539
#define SC_R_VPU 540
#define SC_R_LAST 541
#define SC_R_NONE 0xFFF0
#endif /* DT_BINDINGS_RSCRC_IMX_H */

17
include/eth_phy.h Normal file
View file

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2020 NXP
*/
#ifndef _eth_phy_h_
#define _eth_phy_h_
#include <dm.h>
#include <phy.h>
int eth_phy_binds_nodes(struct udevice *eth_dev);
int eth_phy_set_mdio_bus(struct udevice *eth_dev, struct mii_dev *mdio_bus);
struct mii_dev *eth_phy_get_mdio_bus(struct udevice *eth_dev);
int eth_phy_get_addr(struct udevice *dev);
#endif

View file

@ -16,22 +16,26 @@
* @gf_len: The length of Galois Field. (e.g., 13 or 14)
* @ecc_strength: A number that describes the strength of the ECC
* algorithm.
* @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note
* the first chunk in the page includes both data and
* metadata, so it's a bit larger than this value.
* @ecc_chunk0_size: The size, in bytes, of a first ECC chunk.
* @ecc_chunkn_size: The size, in bytes, of a single ECC chunk after
* the first chunk in the page.
* @ecc_chunk_count: The number of ECC chunks in the page,
* @block_mark_byte_offset: The byte offset in the ECC-based page view at
* which the underlying physical block mark appears.
* @block_mark_bit_offset: The bit offset into the ECC-based page view at
* which the underlying physical block mark appears.
* @ecc_for_meta: The flag to indicate if there is a dedicate ecc
* for meta.
*/
struct bch_geometry {
unsigned int gf_len;
unsigned int ecc_strength;
unsigned int ecc_chunk_size;
unsigned int ecc_chunk0_size;
unsigned int ecc_chunkn_size;
unsigned int ecc_chunk_count;
unsigned int block_mark_byte_offset;
unsigned int block_mark_bit_offset;
unsigned int ecc_for_meta; /* ECC for meta data */
};
struct mxs_nand_info {
@ -39,6 +43,8 @@ struct mxs_nand_info {
struct udevice *dev;
unsigned int max_ecc_strength_supported;
bool use_minimum_ecc;
/* legacy bch geometry flag */
bool legacy_bch_geometry;
int cur_chip;
uint32_t cmd_queue_len;
@ -82,13 +88,15 @@ struct mxs_nand_layout {
u32 ecc0;
u32 datan_size;
u32 eccn;
u32 gf_len;
};
int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info);
int mxs_nand_init_spl(struct nand_chip *nand);
int mxs_nand_setup_ecc(struct mtd_info *mtd);
void mxs_nand_mode_fcb(struct mtd_info *mtd);
void mxs_nand_mode_fcb_62bit(struct mtd_info *mtd);
void mxs_nand_mode_fcb_40bit(struct mtd_info *mtd);
void mxs_nand_mode_normal(struct mtd_info *mtd);
u32 mxs_nand_mark_byte_offset(struct mtd_info *mtd);
u32 mxs_nand_mark_bit_offset(struct mtd_info *mtd);

View file

@ -582,4 +582,5 @@ void spl_perform_fixups(struct spl_image_info *spl_image);
*/
struct image_header *spl_get_load_buffer(ssize_t offset, size_t size);
void spl_save_restore_data(void);
#endif

View file

@ -13,6 +13,7 @@
#include <dm/uclass-internal.h>
#include <net/pcap.h>
#include "eth_internal.h"
#include <eth_phy.h>
DECLARE_GLOBAL_DATA_PTR;
@ -40,8 +41,12 @@ static int eth_errno;
static struct eth_uclass_priv *eth_get_uclass_priv(void)
{
struct uclass *uc;
int ret;
ret = uclass_get(UCLASS_ETH, &uc);
if (ret)
return NULL;
uclass_get(UCLASS_ETH, &uc);
assert(uc);
return uc->priv;
}
@ -102,6 +107,7 @@ struct udevice *eth_get_dev_by_name(const char *devname)
struct udevice *it;
struct uclass *uc;
int len = strlen("eth");
int ret;
/* Must be longer than 3 to be an alias */
if (!strncmp(devname, "eth", len) && strlen(devname) > len) {
@ -109,7 +115,10 @@ struct udevice *eth_get_dev_by_name(const char *devname)
seq = simple_strtoul(startp, &endp, 10);
}
uclass_get(UCLASS_ETH, &uc);
ret = uclass_get(UCLASS_ETH, &uc);
if (ret)
return NULL;
uclass_foreach_dev(it, uc) {
/*
* We need the seq to be valid, so try to probe it.
@ -453,6 +462,10 @@ static int eth_post_bind(struct udevice *dev)
return -EINVAL;
}
#ifdef CONFIG_DM_ETH_PHY
eth_phy_binds_nodes(dev);
#endif
return 0;
}

View file

@ -26,6 +26,8 @@ static int dm_test_cpu(struct unit_test_state *uts)
ut_assert(dev->flags & DM_FLAG_ACTIVATED);
ut_assertok(uclass_get_device_by_name(UCLASS_CPU, "cpu-test1", &dev));
ut_asserteq_ptr(cpu_get_current_dev(), dev);
ut_asserteq(cpu_is_current(dev), 1);
ut_assertok(cpu_get_desc(dev, text, sizeof(text)));
ut_assertok(strcmp(text, "LEG Inc. SuperMegaUltraTurbo CPU No. 1"));