mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
Merge tag 'u-boot-imx-master-20250411' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
CI: https://source.denx.de/u-boot/custodians/u-boot-imx/-/pipelines/25652 - Add i.MX8MP LDB support. - Various phycore-imx93 environment improvements. - Add support for Toradex SMARC iMX8MP.
This commit is contained in:
80
arch/arm/dts/imx8mp-toradex-smarc-dev-u-boot.dtsi
Normal file
80
arch/arm/dts/imx8mp-toradex-smarc-dev-u-boot.dtsi
Normal file
@@ -0,0 +1,80 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
/* Copyright (C) 2024 Toradex */
|
||||
|
||||
#include "imx8mp-u-boot.dtsi"
|
||||
|
||||
/ {
|
||||
sysinfo {
|
||||
compatible = "toradex,sysinfo";
|
||||
};
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&gpio2 {
|
||||
bt_uart_gpio {
|
||||
gpio-hog;
|
||||
gpios = <9 GPIO_ACTIVE_HIGH>;
|
||||
input;
|
||||
line-name = "BT_UART_RXD_GPIO";
|
||||
};
|
||||
};
|
||||
|
||||
&gpio3 {
|
||||
wifi_en_gpio {
|
||||
gpio-hog;
|
||||
gpios = <14 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "CTRL_EN_WIFI";
|
||||
};
|
||||
};
|
||||
|
||||
&gpio5 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&pca9450 {
|
||||
bootph-pre-ram;
|
||||
|
||||
regulators {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
};
|
||||
|
||||
&pinctrl_i2c1 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&pinctrl_i2c1_gpio {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&pinctrl_pmic {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&pinctrl_uart4 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&uart3 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&uart4 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&usdhc1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&usdhc3 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
297
arch/arm/dts/imx8mp-toradex-smarc-dev.dts
Normal file
297
arch/arm/dts/imx8mp-toradex-smarc-dev.dts
Normal file
@@ -0,0 +1,297 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
/* Copyright (C) 2025 Toradex */
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "imx8mp-toradex-smarc.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Toradex SMARC iMX8M Plus on Toradex SMARC Development Board";
|
||||
compatible = "toradex,smarc-imx8mp-dev",
|
||||
"toradex,smarc-imx8mp",
|
||||
"fsl,imx8mp";
|
||||
|
||||
hdmi-connector {
|
||||
compatible = "hdmi-connector";
|
||||
label = "J64";
|
||||
type = "a";
|
||||
|
||||
port {
|
||||
native_hdmi_connector_in: endpoint {
|
||||
remote-endpoint = <&hdmi_tx_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
reg_carrier_1p8v: regulator-carrier-1p8v {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-name = "On-carrier 1V8";
|
||||
};
|
||||
|
||||
sound {
|
||||
compatible = "simple-audio-card";
|
||||
simple-audio-card,bitclock-master = <&codec_dai>;
|
||||
simple-audio-card,format = "i2s";
|
||||
simple-audio-card,frame-master = <&codec_dai>;
|
||||
simple-audio-card,mclk-fs = <256>;
|
||||
simple-audio-card,name = "tdx-smarc-wm8904";
|
||||
simple-audio-card,routing =
|
||||
"Headphone Jack", "HPOUTL",
|
||||
"Headphone Jack", "HPOUTR",
|
||||
"IN2L", "Line In Jack",
|
||||
"IN2R", "Line In Jack",
|
||||
"Microphone Jack", "MICBIAS",
|
||||
"IN1L", "Microphone Jack";
|
||||
simple-audio-card,widgets =
|
||||
"Microphone", "Microphone Jack",
|
||||
"Headphone", "Headphone Jack",
|
||||
"Line", "Line In Jack";
|
||||
|
||||
codec_dai: simple-audio-card,codec {
|
||||
clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1>;
|
||||
sound-dai = <&wm8904_1a>;
|
||||
};
|
||||
|
||||
simple-audio-card,cpu {
|
||||
sound-dai = <&sai1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&aud2htx {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC SPI0 */
|
||||
&ecspi1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC GBE0 */
|
||||
&eqos {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC GBE1 */
|
||||
&fec {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC CAN1 */
|
||||
&flexcan1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC CAN0 */
|
||||
&flexcan2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_gpio7>,
|
||||
<&pinctrl_gpio8>,
|
||||
<&pinctrl_gpio9>,
|
||||
<&pinctrl_gpio10>,
|
||||
<&pinctrl_gpio11>,
|
||||
<&pinctrl_gpio12>,
|
||||
<&pinctrl_gpio13>;
|
||||
};
|
||||
|
||||
&gpio3 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_lvds_dsi_sel>;
|
||||
};
|
||||
|
||||
&gpio4 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_gpio4>, <&pinctrl_gpio6>;
|
||||
};
|
||||
|
||||
&hdmi_pvi {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC HDMI */
|
||||
&hdmi_tx {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
port@1 {
|
||||
hdmi_tx_out: endpoint {
|
||||
remote-endpoint = <&native_hdmi_connector_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&hdmi_tx_phy {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC I2C_LCD */
|
||||
&i2c2 {
|
||||
status = "okay";
|
||||
|
||||
i2c-mux@70 {
|
||||
compatible = "nxp,pca9543";
|
||||
reg = <0x70>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* I2C on DSI Connector Pins 4/6 */
|
||||
i2c_dsi_0: i2c@0 {
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
/* I2C on DSI Connector Pins 52/54 */
|
||||
i2c_dsi_1: i2c@1 {
|
||||
reg = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* SMARC I2C_CAM0 */
|
||||
&i2c3 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC I2C_GP */
|
||||
&i2c4 {
|
||||
/* Audio Codec */
|
||||
wm8904_1a: audio-codec@1a {
|
||||
compatible = "wlf,wm8904";
|
||||
reg = <0x1a>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_sai1>, <&pinctrl_sai1_mclk>;
|
||||
#sound-dai-cells = <0>;
|
||||
clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1>;
|
||||
clock-names = "mclk";
|
||||
AVDD-supply = <®_carrier_1p8v>;
|
||||
CPVDD-supply = <®_carrier_1p8v>;
|
||||
DBVDD-supply = <®_carrier_1p8v>;
|
||||
DCVDD-supply = <®_carrier_1p8v>;
|
||||
MICVDD-supply = <®_carrier_1p8v>;
|
||||
};
|
||||
|
||||
/* On-Carrier Temperature Sensor */
|
||||
temperature-sensor@4f {
|
||||
compatible = "ti,tmp1075";
|
||||
reg = <0x4f>;
|
||||
};
|
||||
|
||||
/* On-Carrier EEPROM */
|
||||
eeprom@57 {
|
||||
compatible = "st,24c02", "atmel,24c02";
|
||||
reg = <0x57>;
|
||||
pagesize = <16>;
|
||||
};
|
||||
};
|
||||
|
||||
/* SMARC I2C_CAM1 */
|
||||
&i2c5 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC I2C_PM */
|
||||
&i2c6 {
|
||||
clock-frequency = <100000>;
|
||||
status = "okay";
|
||||
|
||||
/* Fan controller */
|
||||
fan@18 {
|
||||
compatible = "ti,amc6821";
|
||||
reg = <0x18>;
|
||||
};
|
||||
|
||||
/* Current measurement into module VDD */
|
||||
hwmon@40 {
|
||||
compatible = "ti,ina226";
|
||||
reg = <0x40>;
|
||||
shunt-resistor = <5000>;
|
||||
};
|
||||
};
|
||||
|
||||
&lcdif3 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC PCIE_A, M2 Key B */
|
||||
&pcie {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pcie_phy {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC LCD1_BKLT_PWM */
|
||||
&pwm1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC LCD0_BKLT_PWM */
|
||||
&pwm2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC I2S0 */
|
||||
&sai1 {
|
||||
assigned-clocks = <&clk IMX8MP_CLK_SAI1>;
|
||||
assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>;
|
||||
assigned-clock-rates = <24576000>;
|
||||
fsl,sai-mclk-direction-output;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC HDMI Audio */
|
||||
&sound_hdmi {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC SER0, RS485. Optional M.2 KEY E */
|
||||
&uart1 {
|
||||
linux,rs485-enabled-at-boot-time;
|
||||
rs485-rts-active-low;
|
||||
rs485-rx-during-tx;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC SER2 */
|
||||
&uart2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC SER1, used as the Linux Console */
|
||||
&uart4 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC USB0 */
|
||||
&usb3_0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC USB1..4 */
|
||||
&usb3_1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb3_phy0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb3_phy1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* SMARC SDIO */
|
||||
&usdhc2 {
|
||||
status = "okay";
|
||||
};
|
||||
1284
arch/arm/dts/imx8mp-toradex-smarc.dtsi
Normal file
1284
arch/arm/dts/imx8mp-toradex-smarc.dtsi
Normal file
File diff suppressed because it is too large
Load Diff
@@ -47,6 +47,20 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
idle-states {
|
||||
entry-method = "psci";
|
||||
|
||||
cpu_pd_wait: cpu-pd-wait {
|
||||
compatible = "arm,idle-state";
|
||||
arm,psci-suspend-param = <0x0010033>;
|
||||
local-timer-stop;
|
||||
entry-latency-us = <1000>;
|
||||
exit-latency-us = <700>;
|
||||
min-residency-us = <2700>;
|
||||
wakeup-latency-us = <1500>;
|
||||
};
|
||||
};
|
||||
|
||||
A53_0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a53";
|
||||
@@ -65,6 +79,7 @@
|
||||
nvmem-cell-names = "speed_grade";
|
||||
operating-points-v2 = <&a53_opp_table>;
|
||||
#cooling-cells = <2>;
|
||||
cpu-idle-states = <&cpu_pd_wait>;
|
||||
};
|
||||
|
||||
A53_1: cpu@1 {
|
||||
@@ -83,6 +98,7 @@
|
||||
next-level-cache = <&A53_L2>;
|
||||
operating-points-v2 = <&a53_opp_table>;
|
||||
#cooling-cells = <2>;
|
||||
cpu-idle-states = <&cpu_pd_wait>;
|
||||
};
|
||||
|
||||
A53_2: cpu@2 {
|
||||
@@ -101,6 +117,7 @@
|
||||
next-level-cache = <&A53_L2>;
|
||||
operating-points-v2 = <&a53_opp_table>;
|
||||
#cooling-cells = <2>;
|
||||
cpu-idle-states = <&cpu_pd_wait>;
|
||||
};
|
||||
|
||||
A53_3: cpu@3 {
|
||||
@@ -119,6 +136,7 @@
|
||||
next-level-cache = <&A53_L2>;
|
||||
operating-points-v2 = <&a53_opp_table>;
|
||||
#cooling-cells = <2>;
|
||||
cpu-idle-states = <&cpu_pd_wait>;
|
||||
};
|
||||
|
||||
A53_L2: l2-cache0 {
|
||||
@@ -264,6 +282,7 @@
|
||||
dsp_reserved: dsp@92400000 {
|
||||
reg = <0 0x92400000 0 0x2000000>;
|
||||
no-map;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -726,6 +745,8 @@
|
||||
clk: clock-controller@30380000 {
|
||||
compatible = "fsl,imx8mp-ccm";
|
||||
reg = <0x30380000 0x10000>;
|
||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>,
|
||||
<&clk_ext3>, <&clk_ext4>;
|
||||
@@ -786,6 +807,23 @@
|
||||
reg = <IMX8MP_POWER_DOMAIN_USB2_PHY>;
|
||||
};
|
||||
|
||||
pgc_mlmix: power-domain@4 {
|
||||
#power-domain-cells = <0>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_MLMIX>;
|
||||
clocks = <&clk IMX8MP_CLK_ML_AXI>,
|
||||
<&clk IMX8MP_CLK_ML_AHB>,
|
||||
<&clk IMX8MP_CLK_NPU_ROOT>;
|
||||
assigned-clocks = <&clk IMX8MP_CLK_ML_CORE>,
|
||||
<&clk IMX8MP_CLK_ML_AXI>,
|
||||
<&clk IMX8MP_CLK_ML_AHB>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>,
|
||||
<&clk IMX8MP_SYS_PLL1_800M>,
|
||||
<&clk IMX8MP_SYS_PLL1_800M>;
|
||||
assigned-clock-rates = <1000000000>,
|
||||
<800000000>,
|
||||
<400000000>;
|
||||
};
|
||||
|
||||
pgc_audio: power-domain@5 {
|
||||
#power-domain-cells = <0>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_AUDIOMIX>;
|
||||
@@ -793,10 +831,10 @@
|
||||
<&clk IMX8MP_CLK_AUDIO_AXI>;
|
||||
assigned-clocks = <&clk IMX8MP_CLK_AUDIO_AHB>,
|
||||
<&clk IMX8MP_CLK_AUDIO_AXI_SRC>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>,
|
||||
<&clk IMX8MP_SYS_PLL1_800M>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>,
|
||||
<&clk IMX8MP_SYS_PLL1_800M>;
|
||||
assigned-clock-rates = <400000000>,
|
||||
<600000000>;
|
||||
<800000000>;
|
||||
};
|
||||
|
||||
pgc_gpu2d: power-domain@6 {
|
||||
@@ -818,6 +856,12 @@
|
||||
assigned-clock-rates = <800000000>, <400000000>;
|
||||
};
|
||||
|
||||
pgc_vpumix: power-domain@8 {
|
||||
#power-domain-cells = <0>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_VPUMIX>;
|
||||
clocks = <&clk IMX8MP_CLK_VPU_ROOT>;
|
||||
};
|
||||
|
||||
pgc_gpu3d: power-domain@9 {
|
||||
#power-domain-cells = <0>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_GPU3D>;
|
||||
@@ -833,6 +877,45 @@
|
||||
<&clk IMX8MP_CLK_MEDIA_APB_ROOT>;
|
||||
};
|
||||
|
||||
pgc_vpu_g1: power-domain@11 {
|
||||
#power-domain-cells = <0>;
|
||||
power-domains = <&pgc_vpumix>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_VPU_G1>;
|
||||
clocks = <&clk IMX8MP_CLK_VPU_G1_ROOT>;
|
||||
};
|
||||
|
||||
pgc_vpu_g2: power-domain@12 {
|
||||
#power-domain-cells = <0>;
|
||||
power-domains = <&pgc_vpumix>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_VPU_G2>;
|
||||
clocks = <&clk IMX8MP_CLK_VPU_G2_ROOT>;
|
||||
|
||||
};
|
||||
|
||||
pgc_vpu_vc8000e: power-domain@13 {
|
||||
#power-domain-cells = <0>;
|
||||
power-domains = <&pgc_vpumix>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_VPU_VC8000E>;
|
||||
clocks = <&clk IMX8MP_CLK_VPU_VC8KE_ROOT>;
|
||||
};
|
||||
|
||||
pgc_hdmimix: power-domain@14 {
|
||||
#power-domain-cells = <0>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_HDMIMIX>;
|
||||
clocks = <&clk IMX8MP_CLK_HDMI_ROOT>,
|
||||
<&clk IMX8MP_CLK_HDMI_APB>;
|
||||
assigned-clocks = <&clk IMX8MP_CLK_HDMI_AXI>,
|
||||
<&clk IMX8MP_CLK_HDMI_APB>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_500M>,
|
||||
<&clk IMX8MP_SYS_PLL1_133M>;
|
||||
assigned-clock-rates = <500000000>, <133000000>;
|
||||
};
|
||||
|
||||
pgc_hdmi_phy: power-domain@15 {
|
||||
#power-domain-cells = <0>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_HDMI_PHY>;
|
||||
};
|
||||
|
||||
pgc_mipi_phy2: power-domain@16 {
|
||||
#power-domain-cells = <0>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_MIPI_PHY2>;
|
||||
@@ -853,41 +936,6 @@
|
||||
reg = <IMX8MP_POWER_DOMAIN_MEDIAMIX_ISPDWP>;
|
||||
clocks = <&clk IMX8MP_CLK_MEDIA_ISP_ROOT>;
|
||||
};
|
||||
|
||||
pgc_vpumix: power-domain@19 {
|
||||
#power-domain-cells = <0>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_VPUMIX>;
|
||||
clocks = <&clk IMX8MP_CLK_VPU_ROOT>;
|
||||
};
|
||||
|
||||
pgc_vpu_g1: power-domain@20 {
|
||||
#power-domain-cells = <0>;
|
||||
power-domains = <&pgc_vpumix>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_VPU_G1>;
|
||||
clocks = <&clk IMX8MP_CLK_VPU_G1_ROOT>;
|
||||
};
|
||||
|
||||
pgc_vpu_g2: power-domain@21 {
|
||||
#power-domain-cells = <0>;
|
||||
power-domains = <&pgc_vpumix>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_VPU_G2>;
|
||||
clocks = <&clk IMX8MP_CLK_VPU_G2_ROOT>;
|
||||
};
|
||||
|
||||
pgc_vpu_vc8000e: power-domain@22 {
|
||||
#power-domain-cells = <0>;
|
||||
power-domains = <&pgc_vpumix>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_VPU_VC8000E>;
|
||||
clocks = <&clk IMX8MP_CLK_VPU_VC8KE_ROOT>;
|
||||
};
|
||||
|
||||
pgc_mlmix: power-domain@24 {
|
||||
#power-domain-cells = <0>;
|
||||
reg = <IMX8MP_POWER_DOMAIN_MLMIX>;
|
||||
clocks = <&clk IMX8MP_CLK_ML_AXI>,
|
||||
<&clk IMX8MP_CLK_ML_AHB>,
|
||||
<&clk IMX8MP_CLK_NPU_ROOT>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1231,7 +1279,7 @@
|
||||
compatible = "fsl,imx8mp-usdhc", "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
|
||||
reg = <0x30b40000 0x10000>;
|
||||
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk IMX8MP_CLK_DUMMY>,
|
||||
clocks = <&clk IMX8MP_CLK_IPG_ROOT>,
|
||||
<&clk IMX8MP_CLK_NAND_USDHC_BUS>,
|
||||
<&clk IMX8MP_CLK_USDHC1_ROOT>;
|
||||
clock-names = "ipg", "ahb", "per";
|
||||
@@ -1245,7 +1293,7 @@
|
||||
compatible = "fsl,imx8mp-usdhc", "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
|
||||
reg = <0x30b50000 0x10000>;
|
||||
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk IMX8MP_CLK_DUMMY>,
|
||||
clocks = <&clk IMX8MP_CLK_IPG_ROOT>,
|
||||
<&clk IMX8MP_CLK_NAND_USDHC_BUS>,
|
||||
<&clk IMX8MP_CLK_USDHC2_ROOT>;
|
||||
clock-names = "ipg", "ahb", "per";
|
||||
@@ -1259,7 +1307,7 @@
|
||||
compatible = "fsl,imx8mp-usdhc", "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
|
||||
reg = <0x30b60000 0x10000>;
|
||||
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk IMX8MP_CLK_DUMMY>,
|
||||
clocks = <&clk IMX8MP_CLK_IPG_ROOT>,
|
||||
<&clk IMX8MP_CLK_NAND_USDHC_BUS>,
|
||||
<&clk IMX8MP_CLK_USDHC3_ROOT>;
|
||||
clock-names = "ipg", "ahb", "per";
|
||||
@@ -1501,6 +1549,41 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
aud2htx: aud2htx@30cb0000 {
|
||||
compatible = "fsl,imx8mp-aud2htx";
|
||||
reg = <0x30cb0000 0x10000>;
|
||||
interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_AUD2HTX_IPG>;
|
||||
clock-names = "bus";
|
||||
dmas = <&sdma2 26 2 0>;
|
||||
dma-names = "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
xcvr: xcvr@30cc0000 {
|
||||
compatible = "fsl,imx8mp-xcvr";
|
||||
reg = <0x30cc0000 0x800>,
|
||||
<0x30cc0800 0x400>,
|
||||
<0x30cc0c00 0x080>,
|
||||
<0x30cc0e00 0x080>;
|
||||
reg-names = "ram", "regs", "rxfifo",
|
||||
"txfifo";
|
||||
interrupts = /* XCVR IRQ 0 */
|
||||
<GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
|
||||
/* XCVR IRQ 1 */
|
||||
<GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
|
||||
/* XCVR PHY - SPDIF wakeup IRQ */
|
||||
<GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_EARC_IPG>,
|
||||
<&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_EARC_PHY>,
|
||||
<&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SPBA2_ROOT>,
|
||||
<&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_AUDPLL_ROOT>;
|
||||
clock-names = "ipg", "phy", "spba", "pll_ipg";
|
||||
dmas = <&sdma2 30 2 0>, <&sdma2 31 2 0>;
|
||||
dma-names = "rx", "tx";
|
||||
resets = <&audio_blk_ctrl 0>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
sdma3: dma-controller@30e00000 {
|
||||
@@ -1529,17 +1612,22 @@
|
||||
compatible = "fsl,imx8mp-audio-blk-ctrl";
|
||||
reg = <0x30e20000 0x10000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
clocks = <&clk IMX8MP_CLK_AUDIO_ROOT>,
|
||||
<&clk IMX8MP_CLK_SAI1>,
|
||||
<&clk IMX8MP_CLK_SAI2>,
|
||||
<&clk IMX8MP_CLK_SAI3>,
|
||||
<&clk IMX8MP_CLK_SAI5>,
|
||||
<&clk IMX8MP_CLK_SAI6>,
|
||||
<&clk IMX8MP_CLK_SAI7>;
|
||||
<&clk IMX8MP_CLK_SAI7>,
|
||||
<&clk IMX8MP_CLK_AUDIO_AXI_ROOT>;
|
||||
clock-names = "ahb",
|
||||
"sai1", "sai2", "sai3",
|
||||
"sai5", "sai6", "sai7";
|
||||
"sai5", "sai6", "sai7", "axi";
|
||||
power-domains = <&pgc_audio>;
|
||||
assigned-clocks = <&clk IMX8MP_AUDIO_PLL1>,
|
||||
<&clk IMX8MP_AUDIO_PLL2>;
|
||||
assigned-clock-rates = <393216000>, <361267200>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1604,6 +1692,50 @@
|
||||
};
|
||||
};
|
||||
|
||||
isp_0: isp@32e10000 {
|
||||
compatible = "fsl,imx8mp-isp";
|
||||
reg = <0x32e10000 0x10000>;
|
||||
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk IMX8MP_CLK_MEDIA_ISP_ROOT>,
|
||||
<&clk IMX8MP_CLK_MEDIA_AXI_ROOT>,
|
||||
<&clk IMX8MP_CLK_MEDIA_APB_ROOT>;
|
||||
clock-names = "isp", "aclk", "hclk";
|
||||
power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_ISP>;
|
||||
fsl,blk-ctrl = <&media_blk_ctrl 0>;
|
||||
status = "disabled";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
isp_1: isp@32e20000 {
|
||||
compatible = "fsl,imx8mp-isp";
|
||||
reg = <0x32e20000 0x10000>;
|
||||
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk IMX8MP_CLK_MEDIA_ISP_ROOT>,
|
||||
<&clk IMX8MP_CLK_MEDIA_AXI_ROOT>,
|
||||
<&clk IMX8MP_CLK_MEDIA_APB_ROOT>;
|
||||
clock-names = "isp", "aclk", "hclk";
|
||||
power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_ISP>;
|
||||
fsl,blk-ctrl = <&media_blk_ctrl 1>;
|
||||
status = "disabled";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dewarp: dwe@32e30000 {
|
||||
compatible = "nxp,imx8mp-dw100";
|
||||
reg = <0x32e30000 0x10000>;
|
||||
@@ -1618,15 +1750,16 @@
|
||||
compatible = "fsl,imx8mp-mipi-csi2", "fsl,imx8mm-mipi-csi2";
|
||||
reg = <0x32e40000 0x10000>;
|
||||
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <500000000>;
|
||||
clock-frequency = <250000000>;
|
||||
clocks = <&clk IMX8MP_CLK_MEDIA_APB_ROOT>,
|
||||
<&clk IMX8MP_CLK_MEDIA_CAM1_PIX_ROOT>,
|
||||
<&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT>,
|
||||
<&clk IMX8MP_CLK_MEDIA_AXI_ROOT>;
|
||||
clock-names = "pclk", "wrap", "phy", "axi";
|
||||
assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM1_PIX>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>;
|
||||
assigned-clock-rates = <500000000>;
|
||||
assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM1_PIX>,
|
||||
<&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_250M>,
|
||||
<&clk IMX8MP_CLK_24M>;
|
||||
power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_MIPI_CSI2_1>;
|
||||
status = "disabled";
|
||||
|
||||
@@ -1652,15 +1785,16 @@
|
||||
compatible = "fsl,imx8mp-mipi-csi2", "fsl,imx8mm-mipi-csi2";
|
||||
reg = <0x32e50000 0x10000>;
|
||||
interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <266000000>;
|
||||
clock-frequency = <250000000>;
|
||||
clocks = <&clk IMX8MP_CLK_MEDIA_APB_ROOT>,
|
||||
<&clk IMX8MP_CLK_MEDIA_CAM2_PIX_ROOT>,
|
||||
<&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT>,
|
||||
<&clk IMX8MP_CLK_MEDIA_AXI_ROOT>;
|
||||
clock-names = "pclk", "wrap", "phy", "axi";
|
||||
assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM2_PIX>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>;
|
||||
assigned-clock-rates = <266000000>;
|
||||
assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM2_PIX>,
|
||||
<&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_250M>,
|
||||
<&clk IMX8MP_CLK_24M>;
|
||||
power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_MIPI_CSI2_2>;
|
||||
status = "disabled";
|
||||
|
||||
@@ -1709,6 +1843,13 @@
|
||||
remote-endpoint = <&lcdif1_to_dsim>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
mipi_dsi_out: endpoint {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1791,24 +1932,33 @@
|
||||
clock-names = "apb", "axi", "cam1", "cam2",
|
||||
"disp1", "disp2", "isp", "phy";
|
||||
|
||||
/*
|
||||
* The ISP maximum frequency is 400MHz in normal mode
|
||||
* and 500MHz in overdrive mode. The 400MHz operating
|
||||
* point hasn't been successfully tested yet, so set
|
||||
* IMX8MP_CLK_MEDIA_ISP to 500MHz for the time being.
|
||||
*/
|
||||
assigned-clocks = <&clk IMX8MP_CLK_MEDIA_AXI>,
|
||||
<&clk IMX8MP_CLK_MEDIA_APB>,
|
||||
<&clk IMX8MP_CLK_MEDIA_DISP1_PIX>,
|
||||
<&clk IMX8MP_CLK_MEDIA_DISP2_PIX>,
|
||||
<&clk IMX8MP_CLK_MEDIA_ISP>,
|
||||
<&clk IMX8MP_VIDEO_PLL1>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>,
|
||||
<&clk IMX8MP_SYS_PLL1_800M>,
|
||||
<&clk IMX8MP_VIDEO_PLL1_OUT>,
|
||||
<&clk IMX8MP_VIDEO_PLL1_OUT>;
|
||||
<&clk IMX8MP_VIDEO_PLL1_OUT>,
|
||||
<&clk IMX8MP_SYS_PLL2_500M>;
|
||||
assigned-clock-rates = <500000000>, <200000000>,
|
||||
<0>, <0>, <1039500000>;
|
||||
<0>, <0>, <500000000>,
|
||||
<1039500000>;
|
||||
#power-domain-cells = <1>;
|
||||
|
||||
lvds_bridge: bridge@5c {
|
||||
compatible = "fsl,imx8mp-ldb";
|
||||
reg = <0x5c 0x4>, <0x128 0x4>;
|
||||
reg-names = "ldb", "lvds";
|
||||
clocks = <&clk IMX8MP_CLK_MEDIA_LDB>;
|
||||
clocks = <&clk IMX8MP_CLK_MEDIA_LDB_ROOT>;
|
||||
clock-names = "ldb";
|
||||
assigned-clocks = <&clk IMX8MP_CLK_MEDIA_LDB>;
|
||||
assigned-clock-parents = <&clk IMX8MP_VIDEO_PLL1_OUT>;
|
||||
@@ -1873,6 +2023,136 @@
|
||||
#power-domain-cells = <1>;
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
hdmi_blk_ctrl: blk-ctrl@32fc0000 {
|
||||
compatible = "fsl,imx8mp-hdmi-blk-ctrl", "syscon";
|
||||
reg = <0x32fc0000 0x1000>;
|
||||
clocks = <&clk IMX8MP_CLK_HDMI_APB>,
|
||||
<&clk IMX8MP_CLK_HDMI_ROOT>,
|
||||
<&clk IMX8MP_CLK_HDMI_REF_266M>,
|
||||
<&clk IMX8MP_CLK_HDMI_24M>,
|
||||
<&clk IMX8MP_CLK_HDMI_FDCC_TST>;
|
||||
clock-names = "apb", "axi", "ref_266m", "ref_24m", "fdcc";
|
||||
power-domains = <&pgc_hdmimix>, <&pgc_hdmimix>,
|
||||
<&pgc_hdmimix>, <&pgc_hdmimix>,
|
||||
<&pgc_hdmimix>, <&pgc_hdmimix>,
|
||||
<&pgc_hdmimix>, <&pgc_hdmi_phy>,
|
||||
<&pgc_hdmimix>, <&pgc_hdmimix>;
|
||||
power-domain-names = "bus", "irqsteer", "lcdif",
|
||||
"pai", "pvi", "trng",
|
||||
"hdmi-tx", "hdmi-tx-phy",
|
||||
"hdcp", "hrv";
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
|
||||
irqsteer_hdmi: interrupt-controller@32fc2000 {
|
||||
compatible = "fsl,imx8mp-irqsteer", "fsl,imx-irqsteer";
|
||||
reg = <0x32fc2000 0x1000>;
|
||||
interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
fsl,channel = <1>;
|
||||
fsl,num-irqs = <64>;
|
||||
clocks = <&clk IMX8MP_CLK_HDMI_APB>;
|
||||
clock-names = "ipg";
|
||||
power-domains = <&hdmi_blk_ctrl IMX8MP_HDMIBLK_PD_IRQSTEER>;
|
||||
};
|
||||
|
||||
hdmi_pvi: display-bridge@32fc4000 {
|
||||
compatible = "fsl,imx8mp-hdmi-pvi";
|
||||
reg = <0x32fc4000 0x1000>;
|
||||
interrupt-parent = <&irqsteer_hdmi>;
|
||||
interrupts = <12>;
|
||||
power-domains = <&hdmi_blk_ctrl IMX8MP_HDMIBLK_PD_PVI>;
|
||||
status = "disabled";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
pvi_from_lcdif3: endpoint {
|
||||
remote-endpoint = <&lcdif3_to_pvi>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
pvi_to_hdmi_tx: endpoint {
|
||||
remote-endpoint = <&hdmi_tx_from_pvi>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
lcdif3: display-controller@32fc6000 {
|
||||
compatible = "fsl,imx8mp-lcdif";
|
||||
reg = <0x32fc6000 0x1000>;
|
||||
interrupt-parent = <&irqsteer_hdmi>;
|
||||
interrupts = <8>;
|
||||
clocks = <&hdmi_tx_phy>,
|
||||
<&clk IMX8MP_CLK_HDMI_APB>,
|
||||
<&clk IMX8MP_CLK_HDMI_ROOT>;
|
||||
clock-names = "pix", "axi", "disp_axi";
|
||||
power-domains = <&hdmi_blk_ctrl IMX8MP_HDMIBLK_PD_LCDIF>;
|
||||
status = "disabled";
|
||||
|
||||
port {
|
||||
lcdif3_to_pvi: endpoint {
|
||||
remote-endpoint = <&pvi_from_lcdif3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hdmi_tx: hdmi@32fd8000 {
|
||||
compatible = "fsl,imx8mp-hdmi-tx";
|
||||
reg = <0x32fd8000 0x7eff>;
|
||||
interrupt-parent = <&irqsteer_hdmi>;
|
||||
interrupts = <0>;
|
||||
clocks = <&clk IMX8MP_CLK_HDMI_APB>,
|
||||
<&clk IMX8MP_CLK_HDMI_REF_266M>,
|
||||
<&clk IMX8MP_CLK_32K>,
|
||||
<&hdmi_tx_phy>;
|
||||
clock-names = "iahb", "isfr", "cec", "pix";
|
||||
assigned-clocks = <&clk IMX8MP_CLK_HDMI_REF_266M>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_266M>;
|
||||
power-domains = <&hdmi_blk_ctrl IMX8MP_HDMIBLK_PD_HDMI_TX>;
|
||||
reg-io-width = <1>;
|
||||
status = "disabled";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
hdmi_tx_from_pvi: endpoint {
|
||||
remote-endpoint = <&pvi_to_hdmi_tx>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
/* Point endpoint to the HDMI connector */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hdmi_tx_phy: phy@32fdff00 {
|
||||
compatible = "fsl,imx8mp-hdmi-phy";
|
||||
reg = <0x32fdff00 0x100>;
|
||||
clocks = <&clk IMX8MP_CLK_HDMI_APB>,
|
||||
<&clk IMX8MP_CLK_HDMI_24M>;
|
||||
clock-names = "apb", "ref";
|
||||
assigned-clocks = <&clk IMX8MP_CLK_HDMI_24M>;
|
||||
assigned-clock-parents = <&clk IMX8MP_CLK_24M>;
|
||||
power-domains = <&hdmi_blk_ctrl IMX8MP_HDMIBLK_PD_HDMI_TX_PHY>;
|
||||
#clock-cells = <0>;
|
||||
#phy-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
pcie: pcie@33800000 {
|
||||
@@ -1915,8 +2195,11 @@
|
||||
|
||||
pcie_ep: pcie-ep@33800000 {
|
||||
compatible = "fsl,imx8mp-pcie-ep";
|
||||
reg = <0x33800000 0x000400000>, <0x18000000 0x08000000>;
|
||||
reg-names = "dbi", "addr_space";
|
||||
reg = <0x33800000 0x100000>,
|
||||
<0x18000000 0x8000000>,
|
||||
<0x33900000 0x100000>,
|
||||
<0x33b00000 0x100000>;
|
||||
reg-names = "dbi", "addr_space", "dbi2", "atu";
|
||||
clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
|
||||
<&clk IMX8MP_CLK_HSIO_AXI>,
|
||||
<&clk IMX8MP_CLK_PCIE_ROOT>;
|
||||
@@ -1950,9 +2233,9 @@
|
||||
clock-names = "core", "shader", "bus", "reg";
|
||||
assigned-clocks = <&clk IMX8MP_CLK_GPU3D_CORE>,
|
||||
<&clk IMX8MP_CLK_GPU3D_SHADER_CORE>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>,
|
||||
<&clk IMX8MP_SYS_PLL1_800M>;
|
||||
assigned-clock-rates = <800000000>, <800000000>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>,
|
||||
<&clk IMX8MP_SYS_PLL2_1000M>;
|
||||
assigned-clock-rates = <1000000000>, <1000000000>;
|
||||
power-domains = <&pgc_gpu3d>;
|
||||
};
|
||||
|
||||
@@ -1965,8 +2248,8 @@
|
||||
<&clk IMX8MP_CLK_GPU_AHB>;
|
||||
clock-names = "core", "bus", "reg";
|
||||
assigned-clocks = <&clk IMX8MP_CLK_GPU2D_CORE>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>;
|
||||
assigned-clock-rates = <800000000>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>;
|
||||
assigned-clock-rates = <1000000000>;
|
||||
power-domains = <&pgc_gpu2d>;
|
||||
};
|
||||
|
||||
@@ -2012,6 +2295,18 @@
|
||||
interconnect-names = "g1", "g2", "vc8000e";
|
||||
};
|
||||
|
||||
npu: npu@38500000 {
|
||||
compatible = "vivante,gc";
|
||||
reg = <0x38500000 0x200000>;
|
||||
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk IMX8MP_CLK_NPU_ROOT>,
|
||||
<&clk IMX8MP_CLK_NPU_ROOT>,
|
||||
<&clk IMX8MP_CLK_ML_AXI>,
|
||||
<&clk IMX8MP_CLK_ML_AHB>;
|
||||
clock-names = "core", "shader", "bus", "reg";
|
||||
power-domains = <&pgc_mlmix>;
|
||||
};
|
||||
|
||||
gic: interrupt-controller@38800000 {
|
||||
compatible = "arm,gic-v3";
|
||||
reg = <0x38800000 0x10000>,
|
||||
@@ -2072,6 +2367,7 @@
|
||||
phys = <&usb3_phy0>, <&usb3_phy0>;
|
||||
phy-names = "usb2-phy", "usb3-phy";
|
||||
snps,gfladj-refclk-lpm-sel-quirk;
|
||||
snps,parkmode-disable-ss-quirk;
|
||||
};
|
||||
|
||||
};
|
||||
@@ -2114,6 +2410,7 @@
|
||||
phys = <&usb3_phy1>, <&usb3_phy1>;
|
||||
phy-names = "usb2-phy", "usb3-phy";
|
||||
snps,gfladj-refclk-lpm-sel-quirk;
|
||||
snps,parkmode-disable-ss-quirk;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -291,6 +291,12 @@ config TARGET_KONTRON_PITX_IMX8M
|
||||
select IMX8MQ
|
||||
select IMX8M_LPDDR4
|
||||
|
||||
config TARGET_TORADEX_SMARC_IMX8MP
|
||||
bool "Support Toradex SMARC iMX8M Plus module"
|
||||
select IMX8MP
|
||||
select SUPPORT_SPL
|
||||
select IMX8M_LPDDR4
|
||||
|
||||
config TARGET_VERDIN_IMX8MM
|
||||
bool "Support Toradex Verdin iMX8M Mini module"
|
||||
select IMX8MM
|
||||
@@ -410,6 +416,7 @@ source "board/purism/librem5/Kconfig"
|
||||
source "board/ronetix/imx8mq-cm/Kconfig"
|
||||
source "board/technexion/pico-imx8mq/Kconfig"
|
||||
source "board/variscite/imx8mn_var_som/Kconfig"
|
||||
source "board/toradex/smarc-imx8mp/Kconfig"
|
||||
source "board/toradex/verdin-imx8mm/Kconfig"
|
||||
source "board/toradex/verdin-imx8mp/Kconfig"
|
||||
|
||||
|
||||
@@ -1,26 +1,42 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
|
||||
|
||||
#include <env/phytec/rauc.env>
|
||||
#include <env/phytec/overlays.env>
|
||||
|
||||
bootcmd=
|
||||
mmc dev ${mmcdev};
|
||||
if mmc rescan; then
|
||||
if test ${doraucboot} = 1; then
|
||||
run raucinit;
|
||||
fi;
|
||||
if run loadimage; then
|
||||
run mmcboot;
|
||||
else
|
||||
run netboot;
|
||||
fi;
|
||||
fi;
|
||||
image=Image
|
||||
console=ttyLP0
|
||||
fdt_addr_r=0x83000000
|
||||
fdtoverlay_addr_r=0x830c0000
|
||||
bootenv_addr_r=0x83500000
|
||||
fdt_addr_r=0x90000000
|
||||
fdtoverlay_addr_r=0x900c0000
|
||||
bootenv_addr_r=0x90500000
|
||||
fdtfile=CONFIG_DEFAULT_FDT_FILE
|
||||
ip_dyn=yes
|
||||
prepare_mcore=setenv optargs "${optargs} clk-imx93.mcore_booted"
|
||||
mmcdev=CONFIG_SYS_MMC_ENV_DEV
|
||||
mmcpart=1
|
||||
mmcroot=2
|
||||
mmcautodetect=yes
|
||||
mmcargs=setenv bootargs console=${console},${baudrate} earlycon
|
||||
root=/dev/mmcblk${mmcdev}p${mmcroot} ${raucargs} rootwait rw
|
||||
root=/dev/mmcblk${mmcdev}p${mmcroot} ${raucargs} rootwait rw ${optargs}
|
||||
loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
|
||||
loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} ${fdtfile}
|
||||
mmcboot=
|
||||
echo Booting from mmc ...;
|
||||
if run mmc_load_bootenv; then
|
||||
env import -t ${bootenv_addr_r} ${filesize};
|
||||
if test ${no_bootenv} = 0; then
|
||||
if run mmc_load_bootenv; then
|
||||
env import -t ${bootenv_addr_r} ${filesize};
|
||||
fi;
|
||||
fi;
|
||||
run mmcargs;
|
||||
if run loadfdt; then
|
||||
@@ -31,7 +47,7 @@ mmcboot=
|
||||
fi;
|
||||
nfsroot=/nfs
|
||||
netargs=setenv bootargs console=${console},${baudrate} earlycon
|
||||
root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
|
||||
root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp ${optargs}
|
||||
netboot=
|
||||
echo Booting from net ...;
|
||||
run netargs;
|
||||
@@ -40,8 +56,10 @@ netboot=
|
||||
else
|
||||
setenv get_cmd tftp;
|
||||
fi;
|
||||
if run net_load_bootenv; then
|
||||
env import -t ${bootenv_addr_r} ${filesize};
|
||||
if test ${no_bootenv} = 0; then
|
||||
if run net_load_bootenv; then
|
||||
env import -t ${bootenv_addr_r} ${filesize};
|
||||
fi;
|
||||
fi;
|
||||
${get_cmd} ${loadaddr} ${image};
|
||||
if ${get_cmd} ${fdt_addr_r} ${fdtfile}; then
|
||||
|
||||
@@ -466,10 +466,12 @@ static iomux_v3_cfg_t const rgb_pads[] = {
|
||||
MX6_PAD_EIM_D31__IPU1_DISP1_DATA20 | MUX_PAD_CTRL(OUTPUT_RGB),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IMX_HDMI
|
||||
static void do_enable_hdmi(struct display_info_t const *dev)
|
||||
{
|
||||
imx_enable_hdmi_phy();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void enable_lvds(struct display_info_t const *dev)
|
||||
{
|
||||
@@ -499,7 +501,9 @@ static int detect_default(struct display_info_t const *dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct display_info_t const displays[] = {{
|
||||
struct display_info_t const displays[] = {
|
||||
#ifdef CONFIG_IMX_HDMI
|
||||
{
|
||||
.bus = -1,
|
||||
.addr = 0,
|
||||
.pixfmt = IPU_PIX_FMT_RGB24,
|
||||
@@ -519,7 +523,9 @@ struct display_info_t const displays[] = {{
|
||||
.vsync_len = 10,
|
||||
.sync = FB_SYNC_EXT,
|
||||
.vmode = FB_VMODE_NONINTERLACED
|
||||
} }, {
|
||||
} },
|
||||
#endif
|
||||
{
|
||||
.bus = -1,
|
||||
.addr = 0,
|
||||
.di = 1,
|
||||
@@ -589,7 +595,11 @@ static void setup_display(void)
|
||||
int reg;
|
||||
|
||||
enable_ipu_clock();
|
||||
|
||||
#ifdef CONFIG_IMX_HDMI
|
||||
imx_setup_hdmi();
|
||||
#endif
|
||||
|
||||
/* Turn on LDB0,IPU,IPU DI0 clocks */
|
||||
reg = __raw_readl(&mxc_ccm->CCGR3);
|
||||
reg |= MXC_CCM_CCGR3_LDB_DI0_MASK;
|
||||
|
||||
@@ -164,6 +164,8 @@ const struct toradex_som toradex_modules[] = {
|
||||
{ APALIS_IMX8QP_WIFI_BT_1300MHZ, "Apalis iMX8QP 2GB WB", TARGET_IS_ENABLED(APALIS_IMX8) },
|
||||
{ APALIS_IMX8QP_1300MHZ, "Apalis iMX8QP 2GB", TARGET_IS_ENABLED(APALIS_IMX8) },
|
||||
{ APALIS_IMX8QM_8GB_WIFI_BT_IT_1300MHZ, "Apalis iMX8QM 8GB WB IT", TARGET_IS_ENABLED(APALIS_IMX8) },
|
||||
{ SMARC_IMX95_HEXA_8GB_WB_IT, "SMARC iMX95 Hexa 8GB WB IT", TARGET_IS_ENABLED(TORADEX_SMARC_IMX95) },
|
||||
{ SMARC_IMX8MPQ_4GB_WB_IT, "SMARC iMX8M Plus Quad 4GB WB IT", TARGET_IS_ENABLED(TORADEX_SMARC_IMX8MP) },
|
||||
};
|
||||
|
||||
struct pid4list {
|
||||
|
||||
@@ -122,6 +122,8 @@ enum {
|
||||
APALIS_IMX8QP_WIFI_BT_1300MHZ,
|
||||
APALIS_IMX8QP_1300MHZ,
|
||||
APALIS_IMX8QM_8GB_WIFI_BT_IT_1300MHZ, /* 95 */
|
||||
SMARC_IMX95_HEXA_8GB_WB_IT,
|
||||
SMARC_IMX8MPQ_4GB_WB_IT,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
39
board/toradex/smarc-imx8mp/Kconfig
Normal file
39
board/toradex/smarc-imx8mp/Kconfig
Normal file
@@ -0,0 +1,39 @@
|
||||
if TARGET_TORADEX_SMARC_IMX8MP
|
||||
|
||||
config IMX_CONFIG
|
||||
default "board/toradex/smarc-imx8mp/imximage.cfg"
|
||||
|
||||
config SYS_BOARD
|
||||
default "smarc-imx8mp"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "toradex-smarc-imx8mp"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "toradex"
|
||||
|
||||
config TDX_CFG_BLOCK
|
||||
default y
|
||||
|
||||
config TDX_CFG_BLOCK_2ND_ETHADDR
|
||||
default y
|
||||
|
||||
config TDX_CFG_BLOCK_DEV
|
||||
default "0"
|
||||
|
||||
# Toradex config block in eMMC, at the end of 1st "boot sector"
|
||||
config TDX_CFG_BLOCK_OFFSET
|
||||
default "-512"
|
||||
|
||||
config TDX_CFG_BLOCK_PART
|
||||
default "1"
|
||||
|
||||
config TDX_HAVE_EEPROM_EXTRA
|
||||
default y
|
||||
|
||||
config TDX_HAVE_MMC
|
||||
default y
|
||||
|
||||
source "board/toradex/common/Kconfig"
|
||||
|
||||
endif
|
||||
10
board/toradex/smarc-imx8mp/MAINTAINERS
Normal file
10
board/toradex/smarc-imx8mp/MAINTAINERS
Normal file
@@ -0,0 +1,10 @@
|
||||
Toradex Smarc iMX8M Plus
|
||||
F: arch/arm/dts/imx8mp-toradex-smarc-dev-u-boot.dtsi
|
||||
F: board/toradex/smarc-imx8mp/
|
||||
F: board/toradex/common/
|
||||
F: configs/toradex-smarc-imx8mp_defconfig
|
||||
F: doc/board/toradex/toradex-smarc-imx8mp.rst
|
||||
F: include/configs/toradex-smarc-imx8mp.h
|
||||
M: Francesco Dolcini <francesco.dolcini@toradex.com>
|
||||
S: Maintained
|
||||
W: https://www.toradex.com/computer-on-modules/smarc-arm-family/nxp-imx-8m-plus
|
||||
9
board/toradex/smarc-imx8mp/Makefile
Normal file
9
board/toradex/smarc-imx8mp/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (C) 2024 Toradex
|
||||
|
||||
obj-y += smarc-imx8mp.o
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
obj-y += spl.o
|
||||
obj-$(CONFIG_IMX8M_LPDDR4) += lpddr4_timing.o
|
||||
endif
|
||||
6
board/toradex/smarc-imx8mp/imximage.cfg
Normal file
6
board/toradex/smarc-imx8mp/imximage.cfg
Normal file
@@ -0,0 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* Copyright (C) 2024 Toradex */
|
||||
|
||||
ROM_VERSION v2
|
||||
BOOT_FROM emmc_fastboot
|
||||
LOADER u-boot-spl-ddr.bin 0x920000
|
||||
1903
board/toradex/smarc-imx8mp/lpddr4_timing.c
Normal file
1903
board/toradex/smarc-imx8mp/lpddr4_timing.c
Normal file
File diff suppressed because it is too large
Load Diff
9
board/toradex/smarc-imx8mp/lpddr4_timing.h
Normal file
9
board/toradex/smarc-imx8mp/lpddr4_timing.h
Normal file
@@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* Copyright (C) 2024 Toradex */
|
||||
|
||||
#ifndef __LPDDR4_TIMING_H__
|
||||
#define __LPDDR4_TIMING_H__
|
||||
|
||||
void lpddr4_single_rank_training_patch(void);
|
||||
|
||||
#endif /* __LPDDR4_TIMING_H__ */
|
||||
85
board/toradex/smarc-imx8mp/smarc-imx8mp.c
Normal file
85
board/toradex/smarc-imx8mp/smarc-imx8mp.c
Normal file
@@ -0,0 +1,85 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* Copyright (C) 2024 Toradex */
|
||||
|
||||
#include <init.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm-generic/gpio.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "../common/tdx-cfg-block.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_phys_sdram_size(phys_size_t *size)
|
||||
{
|
||||
if (!size)
|
||||
return -EINVAL;
|
||||
|
||||
*size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE + PHYS_SDRAM_2_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF_LIBFDT) && IS_ENABLED(CONFIG_OF_BOARD_SETUP)
|
||||
static bool board_has_wifi(void)
|
||||
{
|
||||
struct gpio_desc *desc;
|
||||
|
||||
if (!gpio_hog_lookup_name("BT_UART_RXD_GPIO", &desc))
|
||||
return !!dm_gpio_get_value(desc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Module variants with a Wi-Fi/Bluetooth module use UART3 for Bluetooth,
|
||||
* those without use UART3 as the SMARC SER3 UART.
|
||||
* Test for a Wi-Fi module and if none found reassign UART3 interface to
|
||||
* the SMARC SER3 pins.
|
||||
*/
|
||||
static void ft_board_assign_uart(void *blob)
|
||||
{
|
||||
const char *uart_path = "/soc@0/bus@30800000/spba-bus@30800000/serial@30880000";
|
||||
const char *pinctrl_path = "/soc@0/bus@30000000/pinctrl@30330000/uart3grp";
|
||||
int pinctrl_offset;
|
||||
int uart_offset;
|
||||
int bt_offset;
|
||||
u32 phandle;
|
||||
|
||||
if (board_has_wifi())
|
||||
return;
|
||||
|
||||
uart_offset = fdt_path_offset(blob, uart_path);
|
||||
if (uart_offset < 0)
|
||||
return;
|
||||
|
||||
fdt_delprop(blob, uart_offset, "uart-has-rtscts");
|
||||
bt_offset = fdt_subnode_offset(blob, uart_offset, "bluetooth");
|
||||
if (bt_offset < 0)
|
||||
return;
|
||||
|
||||
fdt_del_node(blob, bt_offset);
|
||||
|
||||
pinctrl_offset = fdt_path_offset(blob, pinctrl_path);
|
||||
if (pinctrl_offset < 0)
|
||||
return;
|
||||
|
||||
phandle = fdt_get_phandle(blob, pinctrl_offset);
|
||||
if (phandle < 0)
|
||||
return;
|
||||
|
||||
fdt_setprop_u32(blob, uart_offset, "pinctrl-0", phandle);
|
||||
}
|
||||
|
||||
int ft_board_setup(void *blob, struct bd_info *bd)
|
||||
{
|
||||
ft_board_assign_uart(blob);
|
||||
|
||||
return ft_common_board_setup(blob, bd);
|
||||
}
|
||||
#endif
|
||||
20
board/toradex/smarc-imx8mp/smarc-imx8mp.env
Normal file
20
board/toradex/smarc-imx8mp/smarc-imx8mp.env
Normal file
@@ -0,0 +1,20 @@
|
||||
boot_script_dhcp=boot.scr
|
||||
boot_targets=mmc1 mmc0 dhcp
|
||||
console=ttymxc1
|
||||
fdt_addr_r=0x50200000
|
||||
fdt_board=dev
|
||||
initrd_addr=0x43800000
|
||||
initrd_high=0xffffffffffffffff
|
||||
kernel_addr_r=CONFIG_SYS_LOAD_ADDR
|
||||
kernel_comp_addr_r=0x40200000
|
||||
kernel_comp_size=0x08000000
|
||||
ramdisk_addr_r=0x50300000
|
||||
scriptaddr=0x50280000
|
||||
|
||||
update_uboot=
|
||||
askenv confirm Did you load flash.bin (y/N)?;
|
||||
if test $confirm = y; then
|
||||
setexpr blkcnt ${filesize} + 0x1ff && setexpr blkcnt
|
||||
${blkcnt} / 0x200; mmc dev 0 1; mmc write ${loadaddr} 0x0
|
||||
${blkcnt};
|
||||
fi
|
||||
130
board/toradex/smarc-imx8mp/spl.c
Normal file
130
board/toradex/smarc-imx8mp/spl.c
Normal file
@@ -0,0 +1,130 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* Copyright (C) 2024 Toradex */
|
||||
|
||||
#include <hang.h>
|
||||
#include <init.h>
|
||||
#include <log.h>
|
||||
#include <spl.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/ddr.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/mach-imx/boot_mode.h>
|
||||
#include <dm/device.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/pca9450.h>
|
||||
|
||||
#include "lpddr4_timing.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int spl_board_boot_device(enum boot_device boot_dev_spl)
|
||||
{
|
||||
return BOOT_DEVICE_BOOTROM;
|
||||
}
|
||||
|
||||
void spl_dram_init(void)
|
||||
{
|
||||
/*
|
||||
* Try configuring for dual rank memory falling back to single rank
|
||||
*/
|
||||
if (!ddr_init(&dram_timing)) {
|
||||
puts("DDR configured as dual rank\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lpddr4_single_rank_training_patch();
|
||||
if (!ddr_init(&dram_timing)) {
|
||||
puts("DDR configured as single rank\n");
|
||||
return;
|
||||
}
|
||||
puts("DDR configuration failed\n");
|
||||
}
|
||||
|
||||
void spl_board_init(void)
|
||||
{
|
||||
arch_misc_init();
|
||||
|
||||
/*
|
||||
* Set GIC clock to 500Mhz for OD VDD_SOC. Kernel driver does
|
||||
* not allow to change it. Should set the clock after PMIC
|
||||
* setting done. Default is 400Mhz (system_pll1_800m with div = 2)
|
||||
* set by ROM for ND VDD_SOC
|
||||
*/
|
||||
clock_enable(CCGR_GIC, 0);
|
||||
clock_set_target_val(GIC_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(5));
|
||||
clock_enable(CCGR_GIC, 1);
|
||||
|
||||
puts("Normal Boot\n");
|
||||
}
|
||||
|
||||
int power_init_board(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = pmic_get("pmic@25", &dev);
|
||||
if (ret == -ENODEV) {
|
||||
puts("No pmic@25\n");
|
||||
return 0;
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* BUCKxOUT_DVS0/1 control BUCK123 output */
|
||||
pmic_reg_write(dev, PCA9450_BUCK123_DVS, 0x29);
|
||||
|
||||
/*
|
||||
* Increase VDD_SOC to typical value 0.95V before first
|
||||
* DRAM access, set DVS1 to 0.85V for suspend.
|
||||
* Enable DVS control through PMIC_STBY_REQ and
|
||||
* set B1_ENMODE=1 (ON by PMIC_ON_REQ=H)
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_IMX8M_VDD_SOC_850MV))
|
||||
/* set DVS0 to 0.85v for special case */
|
||||
pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, 0x14);
|
||||
else
|
||||
pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, 0x1c);
|
||||
|
||||
pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS1, 0x14);
|
||||
pmic_reg_write(dev, PCA9450_BUCK1CTRL, 0x59);
|
||||
|
||||
/*
|
||||
* Kernel uses OD/OD freq for SOC.
|
||||
* To avoid timing risk from SOC to ARM,increase VDD_ARM to OD
|
||||
* voltage 0.95V.
|
||||
*/
|
||||
pmic_reg_write(dev, PCA9450_BUCK2OUT_DVS0, 0x1c);
|
||||
|
||||
/* set LDO4 and CONFIG2 to enable the I2C level translator */
|
||||
pmic_reg_write(dev, PCA9450_LDO4CTRL, 0x59);
|
||||
pmic_reg_write(dev, PCA9450_CONFIG2, 0x1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Do not use BSS area in this phase */
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
arch_cpu_init();
|
||||
|
||||
init_uart_clk(3);
|
||||
|
||||
ret = spl_early_init();
|
||||
if (ret) {
|
||||
debug("spl_init() failed: %d\n", ret);
|
||||
hang();
|
||||
}
|
||||
|
||||
preloader_console_init();
|
||||
|
||||
enable_tzc380();
|
||||
|
||||
/* PMIC initialization */
|
||||
power_init_board();
|
||||
|
||||
/* DDR initialization */
|
||||
spl_dram_init();
|
||||
}
|
||||
@@ -35,7 +35,6 @@ CONFIG_REMAKE_ELF=y
|
||||
# CONFIG_ANDROID_BOOT_IMAGE is not set
|
||||
CONFIG_DISTRO_DEFAULTS=y
|
||||
CONFIG_OF_SYSTEM_SETUP=y
|
||||
CONFIG_BOOTCOMMAND="mmc dev ${mmcdev}; if mmc rescan; then if run loadimage; then run mmcboot; else run netboot; fi; fi;"
|
||||
CONFIG_DEFAULT_FDT_FILE="oftree"
|
||||
CONFIG_SYS_CBSIZE=2048
|
||||
CONFIG_SYS_PBSIZE=2074
|
||||
|
||||
@@ -256,6 +256,8 @@ CONFIG_CONSOLE_TRUETYPE=y
|
||||
CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
|
||||
CONFIG_I2C_EDID=y
|
||||
CONFIG_VIDEO_SANDBOX_SDL=y
|
||||
CONFIG_VIDEO_BRIDGE=y
|
||||
CONFIG_VIDEO_BRIDGE_LVDS_CODEC=y
|
||||
CONFIG_OSD=y
|
||||
CONFIG_SANDBOX_OSD=y
|
||||
CONFIG_BMP_16BPP=y
|
||||
|
||||
@@ -220,6 +220,8 @@ CONFIG_CONSOLE_TRUETYPE=y
|
||||
CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
|
||||
CONFIG_I2C_EDID=y
|
||||
CONFIG_VIDEO_SANDBOX_SDL=y
|
||||
CONFIG_VIDEO_BRIDGE=y
|
||||
CONFIG_VIDEO_BRIDGE_LVDS_CODEC=y
|
||||
CONFIG_OSD=y
|
||||
CONFIG_SANDBOX_OSD=y
|
||||
CONFIG_BMP_16BPP=y
|
||||
|
||||
184
configs/toradex-smarc-imx8mp_defconfig
Normal file
184
configs/toradex-smarc-imx8mp_defconfig
Normal file
@@ -0,0 +1,184 @@
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_IMX8M=y
|
||||
CONFIG_TEXT_BASE=0x40200000
|
||||
CONFIG_SPL_GPIO=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_NR_DRAM_BANKS=2
|
||||
CONFIG_ENV_SIZE=0x2000
|
||||
CONFIG_ENV_OFFSET=0xFFFFDE00
|
||||
CONFIG_DM_GPIO=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="imx8mp-toradex-smarc-dev"
|
||||
CONFIG_SPL_TEXT_BASE=0x920000
|
||||
CONFIG_TARGET_TORADEX_SMARC_IMX8MP=y
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
CONFIG_DM_RESET=y
|
||||
CONFIG_SYS_MONITOR_LEN=524288
|
||||
CONFIG_SPL_MMC=y
|
||||
CONFIG_SPL_SERIAL=y
|
||||
CONFIG_SPL_DRIVERS_MISC=y
|
||||
CONFIG_SPL_STACK=0x960000
|
||||
CONFIG_SPL_SYS_MALLOC_F_LEN=0x4000
|
||||
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
|
||||
CONFIG_SPL_BSS_START_ADDR=0x98fc00
|
||||
CONFIG_SPL_BSS_MAX_SIZE=0x400
|
||||
CONFIG_SPL=y
|
||||
CONFIG_IMX_BOOTAUX=y
|
||||
CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x48000000
|
||||
CONFIG_SYS_LOAD_ADDR=0x48200000
|
||||
CONFIG_PCI=y
|
||||
CONFIG_SYS_MEMTEST_START=0x40000000
|
||||
CONFIG_SYS_MEMTEST_END=0x80000000
|
||||
CONFIG_REMAKE_ELF=y
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_EXTERNAL_OFFSET=0x3000
|
||||
CONFIG_FIT_VERBOSE=y
|
||||
CONFIG_SPL_LOAD_FIT=y
|
||||
CONFIG_BOOTSTD_FULL=y
|
||||
# CONFIG_BOOTSTD_BOOTCOMMAND is not set
|
||||
CONFIG_BOOTDELAY=1
|
||||
CONFIG_OF_SYSTEM_SETUP=y
|
||||
CONFIG_BOOTCOMMAND="bootflow scan -b"
|
||||
CONFIG_USE_PREBOOT=y
|
||||
CONFIG_PREBOOT="test -n ${fdtfile} || setenv fdtfile imx8mp-toradex-smarc-dev.dtb"
|
||||
CONFIG_SYS_CBSIZE=2048
|
||||
CONFIG_SYS_PBSIZE=2081
|
||||
CONFIG_LOG=y
|
||||
# CONFIG_DISPLAY_BOARDINFO is not set
|
||||
CONFIG_DISPLAY_BOARDINFO_LATE=y
|
||||
CONFIG_ARCH_MISC_INIT=y
|
||||
CONFIG_SPL_MAX_SIZE=0x26000
|
||||
CONFIG_SPL_BOARD_INIT=y
|
||||
CONFIG_SPL_BOOTROM_SUPPORT=y
|
||||
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
|
||||
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
|
||||
CONFIG_SPL_SYS_MALLOC=y
|
||||
CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y
|
||||
CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x42200000
|
||||
CONFIG_SPL_SYS_MALLOC_SIZE=0x80000
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x300
|
||||
CONFIG_SPL_I2C=y
|
||||
CONFIG_SPL_POWER=y
|
||||
CONFIG_SPL_WATCHDOG=y
|
||||
CONFIG_SYS_PROMPT="SMARC iMX8MP # "
|
||||
# CONFIG_BOOTM_NETBSD is not set
|
||||
CONFIG_CMD_ASKENV=y
|
||||
# CONFIG_CMD_EXPORTENV is not set
|
||||
CONFIG_CRC32_VERIFY=y
|
||||
CONFIG_CMD_MD5SUM=y
|
||||
CONFIG_MD5SUM_VERIFY=y
|
||||
CONFIG_CMD_MEMTEST=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_FUSE=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_PCI=y
|
||||
CONFIG_CMD_READ=y
|
||||
CONFIG_CMD_USB=y
|
||||
CONFIG_CMD_USB_MASS_STORAGE=y
|
||||
CONFIG_CMD_BOOTCOUNT=y
|
||||
CONFIG_CMD_CACHE=y
|
||||
CONFIG_CMD_TIME=y
|
||||
CONFIG_CMD_SYSBOOT=y
|
||||
CONFIG_CMD_UUID=y
|
||||
CONFIG_CMD_REGULATOR=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
# CONFIG_ISO_PARTITION is not set
|
||||
# CONFIG_SPL_EFI_PARTITION is not set
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_ENV_OVERWRITE=y
|
||||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_SYS_MMC_ENV_DEV=0
|
||||
CONFIG_SYS_MMC_ENV_PART=1
|
||||
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
|
||||
CONFIG_USE_ETHPRIME=y
|
||||
CONFIG_ETHPRIME="eth0"
|
||||
CONFIG_VERSION_VARIABLE=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_IP_DEFRAG=y
|
||||
CONFIG_TFTP_BLOCKSIZE=4096
|
||||
CONFIG_SPL_DM=y
|
||||
CONFIG_BOOTCOUNT_LIMIT=y
|
||||
CONFIG_BOOTCOUNT_ENV=y
|
||||
CONFIG_CLK_COMPOSITE_CCF=y
|
||||
CONFIG_CLK_IMX8MP=y
|
||||
CONFIG_FSL_CAAM=y
|
||||
CONFIG_USB_FUNCTION_FASTBOOT=y
|
||||
CONFIG_FASTBOOT_BUF_ADDR=0x44200000
|
||||
CONFIG_FASTBOOT_FLASH=y
|
||||
CONFIG_FASTBOOT_UUU_SUPPORT=y
|
||||
CONFIG_FASTBOOT_FLASH_MMC_DEV=0
|
||||
CONFIG_GPIO_HOG=y
|
||||
CONFIG_SPL_GPIO_HOG=y
|
||||
CONFIG_MXC_GPIO=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_LED=y
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_I2C_EEPROM=y
|
||||
CONFIG_SUPPORT_EMMC_BOOT=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_SPL_MMC_IO_VOLTAGE=y
|
||||
CONFIG_MMC_UHS_SUPPORT=y
|
||||
CONFIG_SPL_MMC_UHS_SUPPORT=y
|
||||
CONFIG_MMC_HS400_ES_SUPPORT=y
|
||||
CONFIG_MMC_HS400_SUPPORT=y
|
||||
CONFIG_SPL_MMC_HS400_SUPPORT=y
|
||||
CONFIG_FSL_USDHC=y
|
||||
CONFIG_PHY_ADDR_ENABLE=y
|
||||
CONFIG_PHY_TI_DP83867=y
|
||||
CONFIG_DM_MDIO=y
|
||||
CONFIG_DM_ETH_PHY=y
|
||||
CONFIG_DWC_ETH_QOS=y
|
||||
CONFIG_DWC_ETH_QOS_IMX=y
|
||||
CONFIG_FEC_MXC=y
|
||||
CONFIG_RGMII=y
|
||||
CONFIG_MII=y
|
||||
CONFIG_NVME_PCI=y
|
||||
CONFIG_PCIE_DW_IMX=y
|
||||
CONFIG_PHY=y
|
||||
CONFIG_PHY_IMX8MQ_USB=y
|
||||
CONFIG_PHY_IMX8M_PCIE=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_SPL_PINCTRL=y
|
||||
CONFIG_PINCTRL_IMX8M=y
|
||||
CONFIG_POWER_DOMAIN=y
|
||||
CONFIG_IMX8M_POWER_DOMAIN=y
|
||||
CONFIG_IMX8MP_HSIOMIX_BLKCTRL=y
|
||||
CONFIG_DM_PMIC=y
|
||||
CONFIG_DM_PMIC_PCA9450=y
|
||||
CONFIG_SPL_DM_PMIC_PCA9450=y
|
||||
CONFIG_DM_REGULATOR_PCA9450=y
|
||||
CONFIG_SPL_DM_REGULATOR_PCA9450=y
|
||||
CONFIG_DM_REGULATOR_FIXED=y
|
||||
CONFIG_DM_REGULATOR_GPIO=y
|
||||
CONFIG_DM_SERIAL=y
|
||||
CONFIG_MXC_UART=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_SPL_SYSRESET=y
|
||||
CONFIG_SYSRESET_PSCI=y
|
||||
CONFIG_SYSRESET_WATCHDOG=y
|
||||
CONFIG_DM_THERMAL=y
|
||||
CONFIG_IMX_TMU=y
|
||||
CONFIG_USB=y
|
||||
# CONFIG_SPL_DM_USB is not set
|
||||
CONFIG_DM_USB_GADGET=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
CONFIG_USB_XHCI_DWC3=y
|
||||
CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
# CONFIG_USB_EHCI_MX7 is not set
|
||||
CONFIG_USB_DWC3=y
|
||||
CONFIG_USB_DWC3_GENERIC=y
|
||||
CONFIG_USB_KEYBOARD=y
|
||||
CONFIG_USB_HOST_ETHER=y
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_GADGET_MANUFACTURER="Toradex"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
|
||||
CONFIG_IMX_WATCHDOG=y
|
||||
CONFIG_HEXDUMP=y
|
||||
@@ -9,6 +9,7 @@ Toradex
|
||||
apalis-imx8
|
||||
colibri_imx7
|
||||
colibri-imx8x
|
||||
smarc-imx8mp
|
||||
verdin-am62
|
||||
verdin-imx8mm
|
||||
verdin-imx8mp
|
||||
|
||||
116
doc/board/toradex/smarc-imx8mp.rst
Normal file
116
doc/board/toradex/smarc-imx8mp.rst
Normal file
@@ -0,0 +1,116 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Toradex SMARC iMX8M Plus Module
|
||||
===============================
|
||||
|
||||
- SoM: https://www.toradex.com/computer-on-modules/smarc-arm-family/nxp-imx-8m-plus
|
||||
- Carrier board: https://www.toradex.com/products/carrier-board/smarc-development-board-kit
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
|
||||
- Build the ARM trusted firmware binary
|
||||
- Get the DDR firmware
|
||||
- Build U-Boot
|
||||
- Flash to eMMC
|
||||
- Boot
|
||||
|
||||
Get and Build the ARM Trusted Firmware (Trusted Firmware A)
|
||||
-----------------------------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ echo "Downloading and building TF-A..."
|
||||
$ git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
|
||||
$ cd trusted-firmware-a
|
||||
|
||||
Then build ATF (TF-A):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ export CROSS_COMPILE=aarch64-linux-gnu-
|
||||
$ make PLAT=imx8mp IMX_BOOT_UART_BASE=0x30a60000 bl31
|
||||
$ cp build/imx8mp/release/bl31.bin ../
|
||||
|
||||
Get the DDR Firmware
|
||||
--------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ cd ..
|
||||
$ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.10.1.bin
|
||||
$ chmod +x firmware-imx-8.10.1.bin
|
||||
$ ./firmware-imx-8.10.1.bin
|
||||
$ cp firmware-imx-8.10.1/firmware/ddr/synopsys/lpddr4*_202006.bin ./
|
||||
|
||||
Build U-Boot
|
||||
------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ export CROSS_COMPILE=aarch64-linux-gnu-
|
||||
$ make toradex-smarc-imx8mp_defconfig
|
||||
$ make
|
||||
|
||||
Flash to eMMC
|
||||
-------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
> tftpboot ${loadaddr} flash.bin
|
||||
> setexpr blkcnt ${filesize} + 0x1ff && setexpr blkcnt ${blkcnt} / 0x200
|
||||
> mmc dev 0 1 && mmc write ${loadaddr} 0x0 ${blkcnt}
|
||||
|
||||
As a convenience, instead of the last two commands, one may also use the update
|
||||
U-Boot wrapper:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
> run update_uboot
|
||||
|
||||
Boot
|
||||
----
|
||||
|
||||
ATF, U-Boot proper and u-boot.dtb images are packed into a FIT image,
|
||||
which is loaded and parsed by SPL.
|
||||
|
||||
Boot sequence is:
|
||||
|
||||
* SPL ---> ATF (TF-A) ---> U-Boot proper
|
||||
|
||||
Output::
|
||||
|
||||
U-Boot SPL 2025.04-rc5-00023-g34c31be81211 (Apr 04 2025 - 15:36:23 +0100)
|
||||
Training FAILED
|
||||
DDR configured as single rank
|
||||
SEC0: RNG instantiated
|
||||
Normal Boot
|
||||
Trying to boot from BOOTROM
|
||||
Boot Stage: Primary boot
|
||||
Find img info 0x4802f200, size 1100
|
||||
Need continue download 1024
|
||||
NOTICE: Do not release JR0 to NS as it can be used by HAB
|
||||
NOTICE: BL31: v2.11.0(release):v2.11.0-723-gbd298f5c30ac
|
||||
NOTICE: BL31: Built : 14:18:43, Apr 4 2025
|
||||
|
||||
|
||||
U-Boot 2025.04-rc5-00023-g34c31be81211 (Apr 04 2025 - 15:36:23 +0100)
|
||||
|
||||
CPU: Freescale i.MX8MP[8] rev1.1 1600 MHz (running at 1200 MHz)
|
||||
CPU: Industrial temperature grade (-40C to 105C) at 72C
|
||||
Reset cause: POR
|
||||
DRAM: 4 GiB
|
||||
Core: 312 devices, 32 uclasses, devicetree: separate
|
||||
WDT: Started watchdog@30280000 with servicing every 1000ms (60s timeout)
|
||||
MMC: FSL_SDHC: 1, FSL_SDHC: 0
|
||||
Loading Environment from MMC... Reading from MMC(0)... OK
|
||||
In: serial@30a60000
|
||||
Out: serial@30a60000
|
||||
Err: serial@30a60000
|
||||
Model: Toradex 0097 SMARC iMX8M Plus Quad 4GB WB IT V1.0A
|
||||
Serial#: 15603364
|
||||
SEC0: RNG instantiated
|
||||
Net: Get shared mii bus on ethernet@30be0000
|
||||
eth1: ethernet@30be0000, eth0: ethernet@30bf0000 [PRIME]
|
||||
Hit any key to stop autoboot: 0
|
||||
SMARC iMX8MP #
|
||||
@@ -312,7 +312,7 @@ drivers/demo/demo-shape.c):
|
||||
.name = "demo_shape_drv",
|
||||
.id = UCLASS_DEMO,
|
||||
.ops = &shape_ops,
|
||||
.priv_data_size = sizeof(struct shape_data),
|
||||
.priv_auto = sizeof(struct shape_data),
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -623,14 +623,27 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
if (!ops->set_parent)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = ops->set_parent(clk, parent);
|
||||
if (ret)
|
||||
ret = clk_enable(parent);
|
||||
if (ret) {
|
||||
printf("Cannot enable parent %s\n", parent->dev->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (CONFIG_IS_ENABLED(CLK_CCF))
|
||||
ret = ops->set_parent(clk, parent);
|
||||
if (ret) {
|
||||
clk_disable(parent);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (CONFIG_IS_ENABLED(CLK_CCF)) {
|
||||
ret = device_reparent(clk->dev, parent->dev);
|
||||
if (ret) {
|
||||
clk_disable(parent);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clk_enable(struct clk *clk)
|
||||
|
||||
@@ -14,7 +14,14 @@
|
||||
|
||||
#include "clk.h"
|
||||
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
static u32 share_count_media;
|
||||
#endif
|
||||
|
||||
static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
static const char * const video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
|
||||
#endif
|
||||
static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
|
||||
static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
|
||||
static const char * const sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", };
|
||||
@@ -31,6 +38,12 @@ static const char * const imx8mp_hsio_axi_sels[] = {"osc_24m", "sys_pll2_500m",
|
||||
"sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
|
||||
"clk_ext4", "audio_pll2_out", };
|
||||
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
static const char * const imx8mp_media_isp_sels[] = {"osc_24m", "sys_pll2_1000m", "sys_pll1_800m",
|
||||
"sys_pll3_out", "sys_pll1_400m", "audio_pll2_out",
|
||||
"clk_ext1", "sys_pll2_500m", };
|
||||
#endif
|
||||
|
||||
static const char * const imx8mp_main_axi_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll1_800m",
|
||||
"sys_pll2_250m", "sys_pll2_1000m", "audio_pll1_out",
|
||||
"video_pll1_out", "sys_pll1_100m",};
|
||||
@@ -43,6 +56,16 @@ static const char * const imx8mp_nand_usdhc_sels[] = {"osc_24m", "sys_pll1_266m"
|
||||
"sys_pll2_200m", "sys_pll1_133m", "sys_pll3_out",
|
||||
"sys_pll2_250m", "audio_pll1_out", };
|
||||
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
static const char * const imx8mp_media_axi_sels[] = {"osc_24m", "sys_pll2_1000m", "sys_pll1_800m",
|
||||
"sys_pll3_out", "sys_pll1_40m", "audio_pll2_out",
|
||||
"clk_ext1", "sys_pll2_500m", };
|
||||
|
||||
static const char * const imx8mp_media_apb_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll1_800m",
|
||||
"sys_pll3_out", "sys_pll1_40m", "audio_pll2_out",
|
||||
"clk_ext1", "sys_pll1_133m", };
|
||||
#endif
|
||||
|
||||
static const char * const imx8mp_noc_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out",
|
||||
"sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out",
|
||||
"video_pll1_out", "audio_pll2_out", };
|
||||
@@ -175,6 +198,17 @@ static const char * const imx8mp_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "s
|
||||
"sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
|
||||
"audio_pll2_out", "sys_pll1_100m", };
|
||||
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
static const char * const imx8mp_media_disp_pix_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out",
|
||||
"audio_pll1_out", "sys_pll1_800m",
|
||||
"sys_pll2_1000m", "sys_pll3_out", "clk_ext4", };
|
||||
|
||||
static const char * const imx8mp_media_ldb_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
|
||||
"sys_pll1_800m", "sys_pll2_1000m",
|
||||
"clk_ext2", "audio_pll2_out",
|
||||
"video_pll1_out", };
|
||||
#endif
|
||||
|
||||
static const char * const imx8mp_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m",
|
||||
"sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out",
|
||||
"video_pll1_out", "clk_ext4", };
|
||||
@@ -199,12 +233,19 @@ static int imx8mp_clk_probe(struct udevice *dev)
|
||||
|
||||
clk_dm(IMX8MP_CLK_DUMMY, clk_register_fixed_rate(NULL, "dummy", 0));
|
||||
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
clk_dm(IMX8MP_VIDEO_PLL1_REF_SEL, imx_clk_mux(dev, "video_pll1_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
|
||||
#endif
|
||||
clk_dm(IMX8MP_DRAM_PLL_REF_SEL, imx_clk_mux(dev, "dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
|
||||
clk_dm(IMX8MP_ARM_PLL_REF_SEL, imx_clk_mux(dev, "arm_pll_ref_sel", base + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
|
||||
clk_dm(IMX8MP_SYS_PLL1_REF_SEL, imx_clk_mux(dev, "sys_pll1_ref_sel", base + 0x94, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
|
||||
clk_dm(IMX8MP_SYS_PLL2_REF_SEL, imx_clk_mux(dev, "sys_pll2_ref_sel", base + 0x104, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
|
||||
clk_dm(IMX8MP_SYS_PLL3_REF_SEL, imx_clk_mux(dev, "sys_pll3_ref_sel", base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
|
||||
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
clk_dm(IMX8MP_VIDEO_PLL1, imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel", base + 0x28,
|
||||
&imx_1443x_pll));
|
||||
#endif
|
||||
clk_dm(IMX8MP_DRAM_PLL, imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50,
|
||||
&imx_1443x_dram_pll));
|
||||
clk_dm(IMX8MP_ARM_PLL, imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84,
|
||||
@@ -216,12 +257,18 @@ static int imx8mp_clk_probe(struct udevice *dev)
|
||||
clk_dm(IMX8MP_SYS_PLL3, imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114,
|
||||
&imx_1416x_pll));
|
||||
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
clk_dm(IMX8MP_VIDEO_PLL1_BYPASS, imx_clk_mux_flags(dev, "video_pll1_bypass", base + 0x28, 16, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT));
|
||||
#endif
|
||||
clk_dm(IMX8MP_DRAM_PLL_BYPASS, imx_clk_mux_flags(dev, "dram_pll_bypass", base + 0x50, 4, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT));
|
||||
clk_dm(IMX8MP_ARM_PLL_BYPASS, imx_clk_mux_flags(dev, "arm_pll_bypass", base + 0x84, 4, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT));
|
||||
clk_dm(IMX8MP_SYS_PLL1_BYPASS, imx_clk_mux_flags(dev, "sys_pll1_bypass", base + 0x94, 4, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT));
|
||||
clk_dm(IMX8MP_SYS_PLL2_BYPASS, imx_clk_mux_flags(dev, "sys_pll2_bypass", base + 0x104, 4, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT));
|
||||
clk_dm(IMX8MP_SYS_PLL3_BYPASS, imx_clk_mux_flags(dev, "sys_pll3_bypass", base + 0x114, 4, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT));
|
||||
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
clk_dm(IMX8MP_VIDEO_PLL1_OUT, imx_clk_gate(dev, "video_pll1_out", "video_pll1_bypass", base + 0x28, 13));
|
||||
#endif
|
||||
clk_dm(IMX8MP_DRAM_PLL_OUT, imx_clk_gate(dev, "dram_pll_out", "dram_pll_bypass", base + 0x50, 13));
|
||||
clk_dm(IMX8MP_ARM_PLL_OUT, imx_clk_gate(dev, "arm_pll_out", "arm_pll_bypass", base + 0x84, 11));
|
||||
clk_dm(IMX8MP_SYS_PLL1_OUT, imx_clk_gate(dev, "sys_pll1_out", "sys_pll1_bypass", base + 0x94, 11));
|
||||
@@ -267,13 +314,23 @@ static int imx8mp_clk_probe(struct udevice *dev)
|
||||
clk_dm(IMX8MP_CLK_A53_DIV, imx_clk_divider2(dev, "arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3));
|
||||
|
||||
clk_dm(IMX8MP_CLK_HSIO_AXI, imx8m_clk_composite(dev, "hsio_axi", imx8mp_hsio_axi_sels, base + 0x8380));
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
clk_dm(IMX8MP_CLK_MEDIA_ISP, imx8m_clk_composite(dev, "media_isp", imx8mp_media_isp_sels, base + 0x8400));
|
||||
#endif
|
||||
clk_dm(IMX8MP_CLK_MAIN_AXI, imx8m_clk_composite_critical(dev, "main_axi", imx8mp_main_axi_sels, base + 0x8800));
|
||||
clk_dm(IMX8MP_CLK_ENET_AXI, imx8m_clk_composite_critical(dev, "enet_axi", imx8mp_enet_axi_sels, base + 0x8880));
|
||||
clk_dm(IMX8MP_CLK_NAND_USDHC_BUS, imx8m_clk_composite_critical(dev, "nand_usdhc_bus", imx8mp_nand_usdhc_sels, base + 0x8900));
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
clk_dm(IMX8MP_CLK_MEDIA_AXI, imx8m_clk_composite(dev, "media_axi", imx8mp_media_axi_sels, base + 0x8a00));
|
||||
clk_dm(IMX8MP_CLK_MEDIA_APB, imx8m_clk_composite(dev, "media_apb", imx8mp_media_apb_sels, base + 0x8a80));
|
||||
#endif
|
||||
clk_dm(IMX8MP_CLK_NOC, imx8m_clk_composite_critical(dev, "noc", imx8mp_noc_sels, base + 0x8d00));
|
||||
clk_dm(IMX8MP_CLK_NOC_IO, imx8m_clk_composite_critical(dev, "noc_io", imx8mp_noc_io_sels, base + 0x8d80));
|
||||
|
||||
clk_dm(IMX8MP_CLK_AHB, imx8m_clk_composite_critical(dev, "ahb_root", imx8mp_ahb_sels, base + 0x9000));
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
clk_dm(IMX8MP_CLK_MEDIA_DISP2_PIX, imx8m_clk_composite(dev, "media_disp2_pix", imx8mp_media_disp_pix_sels, base + 0x9300));
|
||||
#endif
|
||||
|
||||
clk_dm(IMX8MP_CLK_IPG_ROOT, imx_clk_divider2(dev, "ipg_root", "ahb_root", base + 0x9080, 0, 1));
|
||||
|
||||
@@ -312,6 +369,10 @@ static int imx8mp_clk_probe(struct udevice *dev)
|
||||
|
||||
clk_dm(IMX8MP_CLK_WDOG, imx8m_clk_composite(dev, "wdog", imx8mp_wdog_sels, base + 0xb900));
|
||||
clk_dm(IMX8MP_CLK_USDHC3, imx8m_clk_composite(dev, "usdhc3", imx8mp_usdhc3_sels, base + 0xbc80));
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
clk_dm(IMX8MP_CLK_MEDIA_DISP1_PIX, imx8m_clk_composite(dev, "media_disp1_pix", imx8mp_media_disp_pix_sels, base + 0xbe00));
|
||||
clk_dm(IMX8MP_CLK_MEDIA_LDB, imx8m_clk_composite(dev, "media_ldb", imx8mp_media_ldb_sels, base + 0xbf00));
|
||||
#endif
|
||||
|
||||
clk_dm(IMX8MP_CLK_DRAM_ALT_ROOT, imx_clk_fixed_factor(dev, "dram_alt_root", "dram_alt", 1, 4));
|
||||
clk_dm(IMX8MP_CLK_DRAM_CORE, imx_clk_mux2_flags(dev, "dram_core_clk", base + 0x9800, 24, 1, imx8mp_dram_core_sels, ARRAY_SIZE(imx8mp_dram_core_sels), CLK_IS_CRITICAL));
|
||||
@@ -355,6 +416,14 @@ static int imx8mp_clk_probe(struct udevice *dev)
|
||||
clk_dm(IMX8MP_CLK_WDOG2_ROOT, imx_clk_gate4(dev, "wdog2_root_clk", "wdog", base + 0x4540, 0));
|
||||
clk_dm(IMX8MP_CLK_WDOG3_ROOT, imx_clk_gate4(dev, "wdog3_root_clk", "wdog", base + 0x4550, 0));
|
||||
clk_dm(IMX8MP_CLK_HSIO_ROOT, imx_clk_gate4(dev, "hsio_root_clk", "ipg_root", base + 0x45c0, 0));
|
||||
#if CONFIG_IS_ENABLED(VIDEO)
|
||||
clk_dm(IMX8MP_CLK_MEDIA_APB_ROOT, imx_clk_gate2_shared2(dev, "media_apb_root_clk", "media_apb", base + 0x45d0, 0, &share_count_media));
|
||||
clk_dm(IMX8MP_CLK_MEDIA_AXI_ROOT, imx_clk_gate2_shared2(dev, "media_axi_root_clk", "media_axi", base + 0x45d0, 0, &share_count_media));
|
||||
clk_dm(IMX8MP_CLK_MEDIA_DISP1_PIX_ROOT, imx_clk_gate2_shared2(dev, "media_disp1_pix_root_clk", "media_disp1_pix", base + 0x45d0, 0, &share_count_media));
|
||||
clk_dm(IMX8MP_CLK_MEDIA_DISP2_PIX_ROOT, imx_clk_gate2_shared2(dev, "media_disp2_pix_root_clk", "media_disp2_pix", base + 0x45d0, 0, &share_count_media));
|
||||
clk_dm(IMX8MP_CLK_MEDIA_LDB_ROOT, imx_clk_gate2_shared2(dev, "media_ldb_root_clk", "media_ldb", base + 0x45d0, 0, &share_count_media));
|
||||
clk_dm(IMX8MP_CLK_MEDIA_ISP_ROOT, imx_clk_gate2_shared2(dev, "media_isp_root_clk", "media_isp", base + 0x45d0, 0, &share_count_media));
|
||||
#endif
|
||||
|
||||
clk_dm(IMX8MP_CLK_USDHC3_ROOT, imx_clk_gate4(dev, "usdhc3_root_clk", "usdhc3", base + 0x45e0, 0));
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ ofnode ofnode_graph_get_port_by_id(ofnode parent, u32 id)
|
||||
* @id: id for the endpoint
|
||||
*
|
||||
* Return: ofnode in given endpoint or ofnode_null() if not found.
|
||||
* reg and port_reg are ignored when they are -1.
|
||||
* reg_id and id are ignored when they are -1.
|
||||
*/
|
||||
ofnode ofnode_graph_get_endpoint_by_regs(ofnode parent, int reg_id, int id)
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <dm/device.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/lists.h>
|
||||
#include <dm/ofnode_graph.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
#include <dm/util.h>
|
||||
@@ -582,6 +583,24 @@ int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent,
|
||||
ret = uclass_find_device_by_phandle(id, parent, name, &dev);
|
||||
return uclass_get_device_tail(dev, ret, devp);
|
||||
}
|
||||
|
||||
int uclass_get_device_by_endpoint(enum uclass_id class_id, struct udevice *dev,
|
||||
int port_idx, int ep_idx, struct udevice **devp)
|
||||
{
|
||||
ofnode node_source = dev_ofnode(dev);
|
||||
ofnode node_dest = ofnode_graph_get_remote_node(node_source, port_idx, ep_idx);
|
||||
struct udevice *target = NULL;
|
||||
int ret;
|
||||
|
||||
if (!ofnode_valid(node_dest))
|
||||
return -EINVAL;
|
||||
|
||||
ret = uclass_find_device_by_ofnode(class_id, node_dest, &target);
|
||||
if (ret)
|
||||
return -ENODEV;
|
||||
|
||||
return uclass_get_device_tail(target, 0, devp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -163,4 +163,5 @@ U_BOOT_DRIVER(sandbox_scmi_devices) = {
|
||||
.priv_auto = sizeof(struct sandbox_scmi_device_priv),
|
||||
.remove = sandbox_scmi_devices_remove,
|
||||
.probe = sandbox_scmi_devices_probe,
|
||||
.flags = DM_FLAG_DEFAULT_PD_CTRL_OFF,
|
||||
};
|
||||
|
||||
@@ -20,6 +20,16 @@
|
||||
|
||||
#include "smt.h"
|
||||
|
||||
static void scmi_smt_enable_intr(struct scmi_smt *smt, bool enable)
|
||||
{
|
||||
struct scmi_smt_header *hdr = (void *)smt->buf;
|
||||
|
||||
if (enable)
|
||||
hdr->flags |= SCMI_SHMEM_FLAG_INTR_ENABLED;
|
||||
else
|
||||
hdr->flags &= ~SCMI_SHMEM_FLAG_INTR_ENABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shared memory configuration defined by the referred DT phandle
|
||||
* Return with a errno compliant value.
|
||||
@@ -48,6 +58,9 @@ int scmi_dt_get_smt_buffer(struct udevice *dev, struct scmi_smt *smt)
|
||||
if (!smt->buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (device_is_compatible(dev, "arm,scmi") && ofnode_has_property(dev_ofnode(dev), "mboxes"))
|
||||
scmi_smt_enable_intr(smt, true);
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
if (dcache_status())
|
||||
mmu_set_region_dcache_behaviour(ALIGN_DOWN((uintptr_t)smt->buf, MMU_SECTION_SIZE),
|
||||
|
||||
@@ -47,6 +47,13 @@ config IMX8MP_HSIOMIX_BLKCTRL
|
||||
help
|
||||
Enable support for manipulating NXP i.MX8MP on-SoC HSIOMIX block controller.
|
||||
|
||||
config IMX8MP_MEDIAMIX_BLKCTRL
|
||||
bool "Enable i.MX8MP MEDIAMIX domain driver"
|
||||
depends on POWER_DOMAIN && IMX8MP
|
||||
select CLK
|
||||
help
|
||||
Enable support for manipulating NXP i.MX8MP on-SoC MEDIAMIX block controller.
|
||||
|
||||
config MTK_POWER_DOMAIN
|
||||
bool "Enable the MediaTek power domain driver"
|
||||
depends on POWER_DOMAIN && ARCH_MEDIATEK
|
||||
|
||||
@@ -9,6 +9,7 @@ obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
|
||||
obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o imx8-power-domain.o
|
||||
obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o
|
||||
obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o
|
||||
obj-$(CONFIG_IMX8MP_MEDIAMIX_BLKCTRL) += imx8mp-mediamix.o
|
||||
obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
|
||||
obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
|
||||
obj-$(CONFIG_MESON_EE_POWER_DOMAIN) += meson-ee-pwrc.o
|
||||
|
||||
@@ -40,6 +40,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
#define IMX8MN_MIPI_A53_DOMAIN BIT(2)
|
||||
|
||||
#define IMX8MP_HSIOMIX_A53_DOMAIN BIT(19)
|
||||
#define IMX8MP_MEDIAMIX_A53_DOMAIN BIT(12)
|
||||
#define IMX8MP_USB2_PHY_A53_DOMAIN BIT(5)
|
||||
#define IMX8MP_USB1_PHY_A53_DOMAIN BIT(4)
|
||||
#define IMX8MP_PCIE_PHY_A53_DOMAIN BIT(3)
|
||||
@@ -63,6 +64,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
#define IMX8MN_MIPI_SW_Pxx_REQ BIT(0)
|
||||
|
||||
#define IMX8MP_HSIOMIX_Pxx_REQ BIT(17)
|
||||
#define IMX8MP_MEDIAMIX_Pxx_REQ BIT(10)
|
||||
#define IMX8MP_USB2_PHY_Pxx_REQ BIT(3)
|
||||
#define IMX8MP_USB1_PHY_Pxx_REQ BIT(2)
|
||||
#define IMX8MP_PCIE_PHY_SW_Pxx_REQ BIT(1)
|
||||
@@ -81,6 +83,9 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
#define IMX8MP_HSIOMIX_PWRDNACKN BIT(28)
|
||||
#define IMX8MP_HSIOMIX_PWRDNREQN BIT(12)
|
||||
|
||||
#define IMX8MP_MEDIAMIX_PWRDNACKN BIT(30)
|
||||
#define IMX8MP_MEDIAMIX_PWRDNREQN BIT(14)
|
||||
|
||||
/*
|
||||
* The PGC offset values in Reference Manual
|
||||
* (Rev. 1, 01/2018 and the older ones) GPC chapter's
|
||||
@@ -101,6 +106,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
#define IMX8MP_PGC_PCIE 13
|
||||
#define IMX8MP_PGC_USB1 14
|
||||
#define IMX8MP_PGC_USB2 15
|
||||
#define IMX8MP_PGC_MEDIAMIX 22
|
||||
#define IMX8MP_PGC_HSIOMIX 29
|
||||
|
||||
#define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40)
|
||||
@@ -303,6 +309,17 @@ static const struct imx_pgc_domain imx8mp_pgc_domains[] = {
|
||||
.pgc = BIT(IMX8MP_PGC_HSIOMIX),
|
||||
.keep_clocks = true,
|
||||
},
|
||||
|
||||
[IMX8MP_POWER_DOMAIN_MEDIAMIX] = {
|
||||
.bits = {
|
||||
.pxx = IMX8MP_MEDIAMIX_Pxx_REQ,
|
||||
.map = IMX8MP_MEDIAMIX_A53_DOMAIN,
|
||||
.hskreq = IMX8MP_MEDIAMIX_PWRDNREQN,
|
||||
.hskack = IMX8MP_MEDIAMIX_PWRDNACKN,
|
||||
},
|
||||
.pgc = BIT(IMX8MP_PGC_MEDIAMIX),
|
||||
.keep_clocks = true,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct imx_pgc_regs imx8mp_pgc_regs = {
|
||||
|
||||
208
drivers/power/domain/imx8mp-mediamix.c
Normal file
208
drivers/power/domain/imx8mp-mediamix.c
Normal file
@@ -0,0 +1,208 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* i.MX8 MEDIAMIX control block driver
|
||||
* Copyright (C) 2024 Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
* Inspired from Marek Vasut <marex@denx.de> work on the hsiomix driver.
|
||||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <power-domain-uclass.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <dt-bindings/power/imx8mp-power.h>
|
||||
|
||||
#define BLK_SFT_RSTN 0x0
|
||||
#define BLK_CLK_EN 0x4
|
||||
|
||||
struct imx8mp_mediamix_priv {
|
||||
void __iomem *base;
|
||||
struct clk clk_apb;
|
||||
struct clk clk_axi;
|
||||
struct clk clk_disp2;
|
||||
struct power_domain pd_bus;
|
||||
struct power_domain pd_lcdif2;
|
||||
};
|
||||
|
||||
static int imx8mp_mediamix_on(struct power_domain *power_domain)
|
||||
{
|
||||
struct udevice *dev = power_domain->dev;
|
||||
struct imx8mp_mediamix_priv *priv = dev_get_priv(dev);
|
||||
struct power_domain *domain;
|
||||
struct clk *clk;
|
||||
u32 reset;
|
||||
int ret;
|
||||
|
||||
switch (power_domain->id) {
|
||||
case IMX8MP_MEDIABLK_PD_LCDIF_2:
|
||||
domain = &priv->pd_lcdif2;
|
||||
clk = &priv->clk_disp2;
|
||||
reset = BIT(11) | BIT(12) | BIT(24);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Make sure bus domain is awake */
|
||||
ret = power_domain_on(&priv->pd_bus);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Put devices into reset */
|
||||
clrbits_le32(priv->base + BLK_SFT_RSTN, reset);
|
||||
|
||||
/* Enable upstream clocks */
|
||||
ret = clk_enable(&priv->clk_apb);
|
||||
if (ret)
|
||||
goto dis_bus_pd;
|
||||
|
||||
ret = clk_enable(&priv->clk_axi);
|
||||
if (ret)
|
||||
goto dis_apb_clk;
|
||||
|
||||
/* Enable blk-ctrl clock to allow reset to propagate */
|
||||
ret = clk_enable(clk);
|
||||
if (ret)
|
||||
goto dis_axi_clk;
|
||||
setbits_le32(priv->base + BLK_CLK_EN, reset);
|
||||
|
||||
/* Power up upstream GPC domain */
|
||||
ret = power_domain_on(domain);
|
||||
if (ret)
|
||||
goto dis_lcdif_clk;
|
||||
|
||||
/* Wait for reset to propagate */
|
||||
udelay(5);
|
||||
|
||||
/* Release reset */
|
||||
setbits_le32(priv->base + BLK_SFT_RSTN, reset);
|
||||
|
||||
return 0;
|
||||
|
||||
dis_lcdif_clk:
|
||||
clk_disable(clk);
|
||||
dis_axi_clk:
|
||||
clk_disable(&priv->clk_axi);
|
||||
dis_apb_clk:
|
||||
clk_disable(&priv->clk_apb);
|
||||
dis_bus_pd:
|
||||
power_domain_off(&priv->pd_bus);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imx8mp_mediamix_off(struct power_domain *power_domain)
|
||||
{
|
||||
struct udevice *dev = power_domain->dev;
|
||||
struct imx8mp_mediamix_priv *priv = dev_get_priv(dev);
|
||||
struct power_domain *domain;
|
||||
struct clk *clk;
|
||||
u32 reset;
|
||||
|
||||
switch (power_domain->id) {
|
||||
case IMX8MP_MEDIABLK_PD_LCDIF_2:
|
||||
domain = &priv->pd_lcdif2;
|
||||
clk = &priv->clk_disp2;
|
||||
reset = BIT(11) | BIT(12) | BIT(24);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Put devices into reset and disable clocks */
|
||||
clrbits_le32(priv->base + BLK_SFT_RSTN, reset);
|
||||
clrbits_le32(priv->base + BLK_CLK_EN, reset);
|
||||
|
||||
/* Power down upstream GPC domain */
|
||||
power_domain_off(domain);
|
||||
|
||||
clk_disable(clk);
|
||||
clk_disable(&priv->clk_axi);
|
||||
clk_disable(&priv->clk_apb);
|
||||
|
||||
/* Allow bus domain to suspend */
|
||||
power_domain_off(&priv->pd_bus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx8mp_mediamix_of_xlate(struct power_domain *power_domain,
|
||||
struct ofnode_phandle_args *args)
|
||||
{
|
||||
power_domain->id = args->args[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx8mp_mediamix_bind(struct udevice *dev)
|
||||
{
|
||||
/* Bind child lcdif */
|
||||
return dm_scan_fdt_dev(dev);
|
||||
}
|
||||
|
||||
static int imx8mp_mediamix_probe(struct udevice *dev)
|
||||
{
|
||||
struct imx8mp_mediamix_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
priv->base = dev_read_addr_ptr(dev);
|
||||
|
||||
ret = clk_get_by_name(dev, "apb", &priv->clk_apb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_get_by_name(dev, "axi", &priv->clk_axi);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_get_by_name(dev, "disp2", &priv->clk_disp2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = power_domain_get_by_name(dev, &priv->pd_bus, "bus");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = power_domain_get_by_name(dev, &priv->pd_lcdif2, "lcdif2");
|
||||
if (ret < 0)
|
||||
goto free_bus_pd;
|
||||
|
||||
return 0;
|
||||
|
||||
free_bus_pd:
|
||||
power_domain_free(&priv->pd_bus);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imx8mp_mediamix_remove(struct udevice *dev)
|
||||
{
|
||||
struct imx8mp_mediamix_priv *priv = dev_get_priv(dev);
|
||||
|
||||
power_domain_free(&priv->pd_lcdif2);
|
||||
power_domain_free(&priv->pd_bus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id imx8mp_mediamix_ids[] = {
|
||||
{ .compatible = "fsl,imx8mp-media-blk-ctrl" },
|
||||
{ }
|
||||
};
|
||||
|
||||
struct power_domain_ops imx8mp_mediamix_ops = {
|
||||
.on = imx8mp_mediamix_on,
|
||||
.off = imx8mp_mediamix_off,
|
||||
.of_xlate = imx8mp_mediamix_of_xlate,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(imx8mp_mediamix) = {
|
||||
.name = "imx8mp_mediamix",
|
||||
.id = UCLASS_POWER_DOMAIN,
|
||||
.of_match = imx8mp_mediamix_ids,
|
||||
.bind = imx8mp_mediamix_bind,
|
||||
.probe = imx8mp_mediamix_probe,
|
||||
.remove = imx8mp_mediamix_remove,
|
||||
.priv_auto = sizeof(struct imx8mp_mediamix_priv),
|
||||
.ops = &imx8mp_mediamix_ops,
|
||||
};
|
||||
@@ -12,6 +12,10 @@
|
||||
#include <power-domain-uclass.h>
|
||||
#include <dm/device-internal.h>
|
||||
|
||||
struct power_domain_priv {
|
||||
int on_count;
|
||||
};
|
||||
|
||||
static inline struct power_domain_ops *power_domain_dev_ops(struct udevice *dev)
|
||||
{
|
||||
return (struct power_domain_ops *)dev->driver->ops;
|
||||
@@ -107,22 +111,49 @@ int power_domain_free(struct power_domain *power_domain)
|
||||
return ops->rfree ? ops->rfree(power_domain) : 0;
|
||||
}
|
||||
|
||||
int power_domain_on(struct power_domain *power_domain)
|
||||
int power_domain_on_lowlevel(struct power_domain *power_domain)
|
||||
{
|
||||
struct power_domain_priv *priv = dev_get_uclass_priv(power_domain->dev);
|
||||
struct power_domain_ops *ops = power_domain_dev_ops(power_domain->dev);
|
||||
int ret;
|
||||
|
||||
debug("%s(power_domain=%p)\n", __func__, power_domain);
|
||||
|
||||
return ops->on ? ops->on(power_domain) : 0;
|
||||
if (priv->on_count++ > 0)
|
||||
return -EALREADY;
|
||||
|
||||
ret = ops->on ? ops->on(power_domain) : 0;
|
||||
if (ret) {
|
||||
priv->on_count--;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int power_domain_off(struct power_domain *power_domain)
|
||||
int power_domain_off_lowlevel(struct power_domain *power_domain)
|
||||
{
|
||||
struct power_domain_priv *priv = dev_get_uclass_priv(power_domain->dev);
|
||||
struct power_domain_ops *ops = power_domain_dev_ops(power_domain->dev);
|
||||
int ret;
|
||||
|
||||
debug("%s(power_domain=%p)\n", __func__, power_domain);
|
||||
|
||||
return ops->off ? ops->off(power_domain) : 0;
|
||||
if (priv->on_count <= 0) {
|
||||
debug("Power domain %s already off.\n", power_domain->dev->name);
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
if (priv->on_count-- > 1)
|
||||
return -EBUSY;
|
||||
|
||||
ret = ops->off ? ops->off(power_domain) : 0;
|
||||
if (ret) {
|
||||
priv->on_count++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_REAL)
|
||||
@@ -180,4 +211,5 @@ int dev_power_domain_off(struct udevice *dev)
|
||||
UCLASS_DRIVER(power_domain) = {
|
||||
.id = UCLASS_POWER_DOMAIN,
|
||||
.name = "power_domain",
|
||||
.per_device_auto = sizeof(struct power_domain_priv),
|
||||
};
|
||||
|
||||
@@ -51,4 +51,5 @@ U_BOOT_DRIVER(sandbox_power_domain_test) = {
|
||||
.id = UCLASS_MISC,
|
||||
.of_match = sandbox_power_domain_test_ids,
|
||||
.priv_auto = sizeof(struct sandbox_power_domain_test),
|
||||
.flags = DM_FLAG_DEFAULT_PD_CTRL_OFF,
|
||||
};
|
||||
|
||||
@@ -53,7 +53,7 @@ obj-$(CONFIG_VIDEO_COREBOOT) += coreboot.o
|
||||
obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o
|
||||
obj-$(CONFIG_VIDEO_DW_MIPI_DSI) += dw_mipi_dsi.o
|
||||
obj-$(CONFIG_VIDEO_EFI) += efi.o
|
||||
obj-$(CONFIG_VIDEO_IPUV3) += imx/
|
||||
obj-y += imx/
|
||||
obj-$(CONFIG_VIDEO_IVYBRIDGE_IGD) += ivybridge_igd.o
|
||||
obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o
|
||||
obj-$(CONFIG_VIDEO_LCD_ENDEAVORU) += endeavoru-panel.o
|
||||
|
||||
@@ -13,3 +13,12 @@ config IMX_VIDEO_SKIP
|
||||
config IMX_HDMI
|
||||
bool "Enable HDMI support in IPUv3"
|
||||
depends on VIDEO_IPUV3
|
||||
|
||||
config IMX_LDB
|
||||
bool "Freescale i.MX8MP LDB bridge"
|
||||
depends on VIDEO_BRIDGE
|
||||
help
|
||||
Support for i.MX8MP DPI-to-LVDS on-SoC encoder.
|
||||
|
||||
config IMX_LCDIF
|
||||
bool "i.MX LCDIFv3 LCD controller"
|
||||
|
||||
@@ -3,4 +3,6 @@
|
||||
# (C) Copyright 2000-2007
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
|
||||
obj-y += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o
|
||||
obj-$(CONFIG_VIDEO_IPUV3) += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o
|
||||
obj-$(CONFIG_IMX_LDB) += ldb.o
|
||||
obj-$(CONFIG_IMX_LCDIF) += lcdif.o
|
||||
|
||||
314
drivers/video/imx/lcdif.c
Normal file
314
drivers/video/imx/lcdif.c
Normal file
@@ -0,0 +1,314 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* i.MX8 LCD interface driver inspired from the Linux driver
|
||||
* Copyright 2019 NXP
|
||||
* Copyright 2024 Bootlin
|
||||
* Adapted by Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/mach-imx/dma.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <panel.h>
|
||||
#include <power-domain.h>
|
||||
#include <video.h>
|
||||
#include <video_bridge.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "../videomodes.h"
|
||||
|
||||
#define LCDIFV3_CTRL 0x0
|
||||
#define LCDIFV3_CTRL_SET 0x4
|
||||
#define LCDIFV3_CTRL_CLR 0x8
|
||||
#define CTRL_INV_HS BIT(0)
|
||||
#define CTRL_INV_VS BIT(1)
|
||||
#define CTRL_INV_DE BIT(2)
|
||||
#define CTRL_INV_PXCK BIT(3)
|
||||
#define CTRL_CLK_GATE BIT(30)
|
||||
#define CTRL_SW_RESET BIT(31)
|
||||
|
||||
#define LCDIFV3_DISP_PARA 0x10
|
||||
#define DISP_PARA_DISP_MODE_NORMAL 0
|
||||
#define DISP_PARA_LINE_PATTERN_RGB_YUV 0
|
||||
#define DISP_PARA_DISP_ON BIT(31)
|
||||
|
||||
#define LCDIFV3_DISP_SIZE 0x14
|
||||
#define DISP_SIZE_DELTA_X(x) ((x) & 0xffff)
|
||||
#define DISP_SIZE_DELTA_Y(x) ((x) << 16)
|
||||
|
||||
#define LCDIFV3_HSYN_PARA 0x18
|
||||
#define HSYN_PARA_FP_H(x) ((x) & 0xffff)
|
||||
#define HSYN_PARA_BP_H(x) ((x) << 16)
|
||||
|
||||
#define LCDIFV3_VSYN_PARA 0x1C
|
||||
#define VSYN_PARA_FP_V(x) ((x) & 0xffff)
|
||||
#define VSYN_PARA_BP_V(x) ((x) << 16)
|
||||
|
||||
#define LCDIFV3_VSYN_HSYN_WIDTH 0x20
|
||||
#define VSYN_HSYN_PW_H(x) ((x) & 0xffff)
|
||||
#define VSYN_HSYN_PW_V(x) ((x) << 16)
|
||||
|
||||
#define LCDIFV3_CTRLDESCL0_1 0x200
|
||||
#define CTRLDESCL0_1_WIDTH(x) ((x) & 0xffff)
|
||||
#define CTRLDESCL0_1_HEIGHT(x) ((x) << 16)
|
||||
|
||||
#define LCDIFV3_CTRLDESCL0_3 0x208
|
||||
#define CTRLDESCL0_3_PITCH(x) ((x) & 0xFFFF)
|
||||
|
||||
#define LCDIFV3_CTRLDESCL_LOW0_4 0x20C
|
||||
#define LCDIFV3_CTRLDESCL_HIGH0_4 0x210
|
||||
|
||||
#define LCDIFV3_CTRLDESCL0_5 0x214
|
||||
#define CTRLDESCL0_5_YUV_FORMAT(x) (((x) & 0x3) << 14)
|
||||
#define CTRLDESCL0_5_BPP(x) (((x) & 0xf) << 24)
|
||||
#define BPP32_ARGB8888 0x9
|
||||
#define CTRLDESCL0_5_SHADOW_LOAD_EN BIT(30)
|
||||
#define CTRLDESCL0_5_EN BIT(31)
|
||||
|
||||
struct lcdifv3_priv {
|
||||
void __iomem *base;
|
||||
struct clk pix_clk;
|
||||
struct power_domain pd;
|
||||
struct udevice *panel;
|
||||
struct udevice *bridge;
|
||||
};
|
||||
|
||||
static void lcdifv3_set_mode(struct lcdifv3_priv *priv,
|
||||
struct display_timing *timings)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
writel(DISP_SIZE_DELTA_X(timings->hactive.typ) |
|
||||
DISP_SIZE_DELTA_Y(timings->vactive.typ),
|
||||
priv->base + LCDIFV3_DISP_SIZE);
|
||||
|
||||
writel(HSYN_PARA_FP_H(timings->hfront_porch.typ) |
|
||||
HSYN_PARA_BP_H(timings->hback_porch.typ),
|
||||
priv->base + LCDIFV3_HSYN_PARA);
|
||||
|
||||
writel(VSYN_PARA_BP_V(timings->vback_porch.typ) |
|
||||
VSYN_PARA_FP_V(timings->vfront_porch.typ),
|
||||
priv->base + LCDIFV3_VSYN_PARA);
|
||||
|
||||
writel(VSYN_HSYN_PW_H(timings->hsync_len.typ) |
|
||||
VSYN_HSYN_PW_V(timings->vsync_len.typ),
|
||||
priv->base + LCDIFV3_VSYN_HSYN_WIDTH);
|
||||
|
||||
writel(CTRLDESCL0_1_WIDTH(timings->hactive.typ) |
|
||||
CTRLDESCL0_1_HEIGHT(timings->vactive.typ),
|
||||
priv->base + LCDIFV3_CTRLDESCL0_1);
|
||||
|
||||
if (timings->flags & DISPLAY_FLAGS_HSYNC_LOW)
|
||||
writel(CTRL_INV_HS, priv->base + LCDIFV3_CTRL_SET);
|
||||
else
|
||||
writel(CTRL_INV_HS, priv->base + LCDIFV3_CTRL_CLR);
|
||||
|
||||
if (timings->flags & DISPLAY_FLAGS_VSYNC_LOW)
|
||||
writel(CTRL_INV_VS, priv->base + LCDIFV3_CTRL_SET);
|
||||
else
|
||||
writel(CTRL_INV_VS, priv->base + LCDIFV3_CTRL_CLR);
|
||||
|
||||
if (timings->flags & DISPLAY_FLAGS_DE_LOW)
|
||||
writel(CTRL_INV_DE, priv->base + LCDIFV3_CTRL_SET);
|
||||
else
|
||||
writel(CTRL_INV_DE, priv->base + LCDIFV3_CTRL_CLR);
|
||||
|
||||
if (timings->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
|
||||
writel(CTRL_INV_PXCK, priv->base + LCDIFV3_CTRL_SET);
|
||||
else
|
||||
writel(CTRL_INV_PXCK, priv->base + LCDIFV3_CTRL_CLR);
|
||||
|
||||
writel(0, priv->base + LCDIFV3_DISP_PARA);
|
||||
|
||||
reg = readl(priv->base + LCDIFV3_CTRLDESCL0_5);
|
||||
reg &= ~(CTRLDESCL0_5_BPP(0xf) | CTRLDESCL0_5_YUV_FORMAT(0x3));
|
||||
reg |= CTRLDESCL0_5_BPP(BPP32_ARGB8888);
|
||||
writel(reg, priv->base + LCDIFV3_CTRLDESCL0_5);
|
||||
}
|
||||
|
||||
static void lcdifv3_enable_controller(struct lcdifv3_priv *priv)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = readl(priv->base + LCDIFV3_DISP_PARA);
|
||||
reg |= DISP_PARA_DISP_ON;
|
||||
writel(reg, priv->base + LCDIFV3_DISP_PARA);
|
||||
|
||||
reg = readl(priv->base + LCDIFV3_CTRLDESCL0_5);
|
||||
reg |= CTRLDESCL0_5_EN;
|
||||
writel(reg, priv->base + LCDIFV3_CTRLDESCL0_5);
|
||||
}
|
||||
|
||||
static int lcdifv3_video_sync(struct udevice *dev)
|
||||
{
|
||||
struct lcdifv3_priv *priv = dev_get_priv(dev);
|
||||
u32 reg;
|
||||
|
||||
reg = readl(priv->base + LCDIFV3_CTRLDESCL0_5);
|
||||
reg |= CTRLDESCL0_5_SHADOW_LOAD_EN;
|
||||
writel(reg, priv->base + LCDIFV3_CTRLDESCL0_5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lcdifv3_init(struct udevice *dev, struct display_timing *timings)
|
||||
{
|
||||
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
|
||||
struct lcdifv3_priv *priv = dev_get_priv(dev);
|
||||
|
||||
clk_set_rate(&priv->pix_clk, timings->pixelclock.typ);
|
||||
|
||||
writel(CTRL_SW_RESET | CTRL_CLK_GATE, priv->base + LCDIFV3_CTRL_CLR);
|
||||
udelay(10);
|
||||
|
||||
lcdifv3_set_mode(priv, timings);
|
||||
|
||||
writel(plat->base & 0xFFFFFFFF, priv->base + LCDIFV3_CTRLDESCL_LOW0_4);
|
||||
writel(plat->base >> 32, priv->base + LCDIFV3_CTRLDESCL_HIGH0_4);
|
||||
|
||||
writel(CTRLDESCL0_3_PITCH(timings->hactive.typ * 4), /* 32bpp */
|
||||
priv->base + LCDIFV3_CTRLDESCL0_3);
|
||||
|
||||
lcdifv3_enable_controller(priv);
|
||||
}
|
||||
|
||||
static int lcdifv3_video_probe(struct udevice *dev)
|
||||
{
|
||||
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
|
||||
struct video_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
struct lcdifv3_priv *priv = dev_get_priv(dev);
|
||||
struct clk axi_clk, disp_axi_clk;
|
||||
struct display_timing timings;
|
||||
u32 fb_start, fb_end;
|
||||
int ret;
|
||||
|
||||
ret = power_domain_get(dev, &priv->pd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_get_by_name(dev, "pix", &priv->pix_clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_get_by_name(dev, "axi", &axi_clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_get_by_name(dev, "disp_axi", &disp_axi_clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = power_domain_on(&priv->pd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_enable(&priv->pix_clk);
|
||||
if (ret)
|
||||
goto dis_pd;
|
||||
|
||||
ret = clk_enable(&axi_clk);
|
||||
if (ret)
|
||||
goto dis_pix_clk;
|
||||
|
||||
ret = clk_enable(&disp_axi_clk);
|
||||
if (ret)
|
||||
goto dis_axi_clk;
|
||||
|
||||
priv->base = dev_remap_addr(dev);
|
||||
if (!priv->base) {
|
||||
ret = -EINVAL;
|
||||
goto dis_clks;
|
||||
}
|
||||
|
||||
/* Attach bridge */
|
||||
ret = uclass_get_device_by_endpoint(UCLASS_VIDEO_BRIDGE, dev,
|
||||
-1, -1, &priv->bridge);
|
||||
if (ret)
|
||||
goto dis_clks;
|
||||
|
||||
ret = video_bridge_attach(priv->bridge);
|
||||
if (ret)
|
||||
goto dis_clks;
|
||||
|
||||
ret = video_bridge_set_backlight(priv->bridge, 80);
|
||||
if (ret)
|
||||
goto dis_clks;
|
||||
|
||||
/* Attach panels */
|
||||
ret = uclass_get_device_by_endpoint(UCLASS_PANEL, priv->bridge,
|
||||
1, -1, &priv->panel);
|
||||
if (ret) {
|
||||
ret = uclass_get_device_by_endpoint(UCLASS_PANEL, priv->bridge,
|
||||
2, -1, &priv->panel);
|
||||
if (ret)
|
||||
goto dis_clks;
|
||||
}
|
||||
|
||||
ret = panel_get_display_timing(priv->panel, &timings);
|
||||
if (ret) {
|
||||
ret = ofnode_decode_display_timing(dev_ofnode(priv->panel),
|
||||
0, &timings);
|
||||
if (ret) {
|
||||
printf("Cannot decode panel timings (%d)\n", ret);
|
||||
goto dis_clks;
|
||||
}
|
||||
}
|
||||
|
||||
lcdifv3_init(dev, &timings);
|
||||
|
||||
/* Only support 32bpp for now */
|
||||
uc_priv->bpix = VIDEO_BPP32;
|
||||
uc_priv->xsize = timings.hactive.typ;
|
||||
uc_priv->ysize = timings.vactive.typ;
|
||||
|
||||
/* Enable dcache for the frame buffer */
|
||||
fb_start = plat->base & ~(MMU_SECTION_SIZE - 1);
|
||||
fb_end = ALIGN(plat->base + plat->size, 1 << MMU_SECTION_SHIFT);
|
||||
mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start,
|
||||
DCACHE_WRITEBACK);
|
||||
video_set_flush_dcache(dev, true);
|
||||
|
||||
return 0;
|
||||
|
||||
dis_clks:
|
||||
clk_disable(&disp_axi_clk);
|
||||
dis_axi_clk:
|
||||
clk_disable(&axi_clk);
|
||||
dis_pix_clk:
|
||||
clk_disable(&priv->pix_clk);
|
||||
dis_pd:
|
||||
power_domain_off(&priv->pd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lcdifv3_video_bind(struct udevice *dev)
|
||||
{
|
||||
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
|
||||
|
||||
/* Max size supported by LCDIF */
|
||||
plat->size = 1920 * 1080 * VNBYTES(VIDEO_BPP32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id lcdifv3_video_ids[] = {
|
||||
{ .compatible = "fsl,imx8mp-lcdif" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct video_ops lcdifv3_video_ops = {
|
||||
.video_sync = lcdifv3_video_sync,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(lcdifv3_video) = {
|
||||
.name = "lcdif",
|
||||
.id = UCLASS_VIDEO,
|
||||
.of_match = lcdifv3_video_ids,
|
||||
.bind = lcdifv3_video_bind,
|
||||
.ops = &lcdifv3_video_ops,
|
||||
.probe = lcdifv3_video_probe,
|
||||
.priv_auto = sizeof(struct lcdifv3_priv),
|
||||
.flags = DM_FLAG_PRE_RELOC | DM_FLAG_OS_PREPARE,
|
||||
};
|
||||
251
drivers/video/imx/ldb.c
Normal file
251
drivers/video/imx/ldb.c
Normal file
@@ -0,0 +1,251 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Derived work from:
|
||||
* Philippe Cornu <philippe.cornu@st.com>
|
||||
* Yannick Fertre <yannick.fertre@st.com>
|
||||
* Adapted by Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
*/
|
||||
|
||||
#define LOG_CATEGORY UCLASS_VIDEO_BRIDGE
|
||||
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <panel.h>
|
||||
#include <video_bridge.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define LDB_CTRL_CH0_ENABLE BIT(0)
|
||||
#define LDB_CTRL_CH1_ENABLE BIT(2)
|
||||
#define LDB_CTRL_CH0_DATA_WIDTH BIT(5)
|
||||
#define LDB_CTRL_CH0_BIT_MAPPING BIT(6)
|
||||
#define LDB_CTRL_CH1_DATA_WIDTH BIT(7)
|
||||
#define LDB_CTRL_CH1_BIT_MAPPING BIT(8)
|
||||
#define LDB_CTRL_DI0_VSYNC_POLARITY BIT(9)
|
||||
#define LDB_CTRL_DI1_VSYNC_POLARITY BIT(10)
|
||||
|
||||
#define LVDS_CTRL_CH0_EN BIT(0)
|
||||
#define LVDS_CTRL_CH1_EN BIT(1)
|
||||
#define LVDS_CTRL_VBG_EN BIT(2)
|
||||
#define LVDS_CTRL_PRE_EMPH_EN BIT(4)
|
||||
#define LVDS_CTRL_PRE_EMPH_ADJ(n) (((n) & 0x7) << 5)
|
||||
#define LVDS_CTRL_CC_ADJ(n) (((n) & 0x7) << 11)
|
||||
|
||||
struct imx_ldb_priv {
|
||||
struct clk ldb_clk;
|
||||
void __iomem *ldb_ctrl;
|
||||
void __iomem *lvds_ctrl;
|
||||
struct udevice *lvds1;
|
||||
struct udevice *lvds2;
|
||||
};
|
||||
|
||||
static int imx_ldb_set_backlight(struct udevice *dev, int percent)
|
||||
{
|
||||
struct imx_ldb_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
if (priv->lvds1) {
|
||||
ret = panel_enable_backlight(priv->lvds1);
|
||||
if (ret) {
|
||||
debug("ldb: Cannot enable lvds1 backlight\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = panel_set_backlight(priv->lvds1, percent);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (priv->lvds2) {
|
||||
ret = panel_enable_backlight(priv->lvds2);
|
||||
if (ret) {
|
||||
debug("ldb: Cannot enable lvds2 backlight\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = panel_set_backlight(priv->lvds2, percent);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_ldb_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
struct imx_ldb_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
uclass_get_device_by_endpoint(UCLASS_PANEL, dev, 1, -1, &priv->lvds1);
|
||||
uclass_get_device_by_endpoint(UCLASS_PANEL, dev, 2, -1, &priv->lvds2);
|
||||
if (!priv->lvds1 && !priv->lvds2) {
|
||||
debug("ldb: No remote panel for '%s' (ret=%d)\n",
|
||||
dev_read_name(dev), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The block has a mysterious x7 internal divisor (x3.5 in dual configuration) */
|
||||
#define IMX_LDB_INTERNAL_DIVISOR(x) (((x) * 70) / 10)
|
||||
#define IMX_LDB_INTERNAL_DIVISOR_DUAL(x) (((x) * 35) / 10)
|
||||
|
||||
static ulong imx_ldb_input_rate(struct imx_ldb_priv *priv,
|
||||
struct display_timing *timings)
|
||||
{
|
||||
ulong target_rate = timings->pixelclock.typ;
|
||||
|
||||
if (priv->lvds1 && priv->lvds2)
|
||||
return IMX_LDB_INTERNAL_DIVISOR_DUAL(target_rate);
|
||||
|
||||
return IMX_LDB_INTERNAL_DIVISOR(target_rate);
|
||||
}
|
||||
|
||||
static int imx_ldb_attach(struct udevice *dev)
|
||||
{
|
||||
struct imx_ldb_priv *priv = dev_get_priv(dev);
|
||||
struct display_timing timings;
|
||||
bool format_jeida = false;
|
||||
bool format_24bpp = true;
|
||||
u32 ldb_ctrl = 0, lvds_ctrl;
|
||||
ulong ldb_rate;
|
||||
int ret;
|
||||
|
||||
/* TODO: update the 24bpp/jeida booleans with proper checks when they
|
||||
* will be supported.
|
||||
*/
|
||||
if (priv->lvds1) {
|
||||
ret = panel_get_display_timing(priv->lvds1, &timings);
|
||||
if (ret) {
|
||||
ret = ofnode_decode_display_timing(dev_ofnode(priv->lvds1),
|
||||
0, &timings);
|
||||
if (ret) {
|
||||
printf("Cannot decode lvds1 timings (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ldb_ctrl |= LDB_CTRL_CH0_ENABLE;
|
||||
if (format_24bpp)
|
||||
ldb_ctrl |= LDB_CTRL_CH0_DATA_WIDTH;
|
||||
if (format_jeida)
|
||||
ldb_ctrl |= LDB_CTRL_CH0_BIT_MAPPING;
|
||||
if (timings.flags & DISPLAY_FLAGS_VSYNC_HIGH)
|
||||
ldb_ctrl |= LDB_CTRL_DI0_VSYNC_POLARITY;
|
||||
}
|
||||
|
||||
if (priv->lvds2) {
|
||||
ret = panel_get_display_timing(priv->lvds2, &timings);
|
||||
if (ret) {
|
||||
ret = ofnode_decode_display_timing(dev_ofnode(priv->lvds2),
|
||||
0, &timings);
|
||||
if (ret) {
|
||||
printf("Cannot decode lvds2 timings (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ldb_ctrl |= LDB_CTRL_CH1_ENABLE;
|
||||
if (format_24bpp)
|
||||
ldb_ctrl |= LDB_CTRL_CH1_DATA_WIDTH;
|
||||
if (format_jeida)
|
||||
ldb_ctrl |= LDB_CTRL_CH1_BIT_MAPPING;
|
||||
if (timings.flags & DISPLAY_FLAGS_VSYNC_HIGH)
|
||||
ldb_ctrl |= LDB_CTRL_DI1_VSYNC_POLARITY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Not all pixel clocks will work, as the final rate (after internal
|
||||
* integer division) should be identical to the LCDIF clock, otherwise
|
||||
* the rendering will appear resized/shimmering.
|
||||
*/
|
||||
ldb_rate = imx_ldb_input_rate(priv, &timings);
|
||||
clk_set_rate(&priv->ldb_clk, ldb_rate);
|
||||
|
||||
writel(ldb_ctrl, priv->ldb_ctrl);
|
||||
|
||||
lvds_ctrl = LVDS_CTRL_CC_ADJ(2) | LVDS_CTRL_PRE_EMPH_EN |
|
||||
LVDS_CTRL_PRE_EMPH_ADJ(3) | LVDS_CTRL_VBG_EN;
|
||||
writel(lvds_ctrl, priv->lvds_ctrl);
|
||||
|
||||
/* Wait for VBG to stabilize. */
|
||||
udelay(15);
|
||||
|
||||
if (priv->lvds1)
|
||||
lvds_ctrl |= LVDS_CTRL_CH0_EN;
|
||||
if (priv->lvds2)
|
||||
lvds_ctrl |= LVDS_CTRL_CH1_EN;
|
||||
|
||||
writel(lvds_ctrl, priv->lvds_ctrl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_ldb_probe(struct udevice *dev)
|
||||
{
|
||||
struct imx_ldb_priv *priv = dev_get_priv(dev);
|
||||
struct udevice *parent = dev_get_parent(dev);
|
||||
fdt_addr_t parent_addr, child_addr;
|
||||
int ret;
|
||||
|
||||
ret = clk_get_by_name(dev, "ldb", &priv->ldb_clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
parent_addr = dev_read_addr(parent);
|
||||
if (parent_addr == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
child_addr = dev_read_addr_name(dev, "ldb");
|
||||
if (child_addr == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
priv->ldb_ctrl = map_physmem(parent_addr + child_addr, 0, MAP_NOCACHE);
|
||||
if (!priv->ldb_ctrl)
|
||||
return -EINVAL;
|
||||
|
||||
child_addr = dev_read_addr_name(dev, "lvds");
|
||||
if (child_addr == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
priv->lvds_ctrl = map_physmem(parent_addr + child_addr, 0, MAP_NOCACHE);
|
||||
if (!priv->lvds_ctrl)
|
||||
return -EINVAL;
|
||||
|
||||
ret = clk_enable(&priv->ldb_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = video_bridge_set_active(dev, true);
|
||||
if (ret)
|
||||
goto dis_clk;
|
||||
|
||||
return 0;
|
||||
|
||||
dis_clk:
|
||||
clk_disable(&priv->ldb_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct video_bridge_ops imx_ldb_ops = {
|
||||
.attach = imx_ldb_attach,
|
||||
.set_backlight = imx_ldb_set_backlight,
|
||||
};
|
||||
|
||||
static const struct udevice_id imx_ldb_ids[] = {
|
||||
{ .compatible = "fsl,imx8mp-ldb"},
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(imx_ldb) = {
|
||||
.name = "imx-lvds-display-bridge",
|
||||
.id = UCLASS_VIDEO_BRIDGE,
|
||||
.of_match = imx_ldb_ids,
|
||||
.probe = imx_ldb_probe,
|
||||
.of_to_plat = imx_ldb_of_to_plat,
|
||||
.ops = &imx_ldb_ops,
|
||||
.priv_auto = sizeof(struct imx_ldb_priv),
|
||||
};
|
||||
28
include/configs/toradex-smarc-imx8mp.h
Normal file
28
include/configs/toradex-smarc-imx8mp.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* Copyright (C) 2024 Toradex */
|
||||
|
||||
#ifndef __TORADEX_SMARC_IMX8MP_H
|
||||
#define __TORADEX_SMARC_IMX8MP_H
|
||||
|
||||
#include <asm/arch/imx-regs.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#define CFG_SYS_UBOOT_BASE \
|
||||
(QSPI0_AMBA_BASE + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512)
|
||||
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
/* malloc f used before GD_FLG_FULL_MALLOC_INIT set */
|
||||
#define CFG_MALLOC_F_ADDR 0x184000
|
||||
#endif /* CONFIG_SPL_BUILD */
|
||||
|
||||
#define CFG_SYS_INIT_RAM_ADDR 0x40000000
|
||||
#define CFG_SYS_INIT_RAM_SIZE SZ_512K
|
||||
|
||||
/* i.MX 8M Plus supports max. 8GB memory in two albeit consecutive banks */
|
||||
#define CFG_SYS_SDRAM_BASE 0x40000000
|
||||
#define PHYS_SDRAM 0x40000000
|
||||
#define PHYS_SDRAM_SIZE (SZ_2G + SZ_1G)
|
||||
#define PHYS_SDRAM_2 0x100000000
|
||||
#define PHYS_SDRAM_2_SIZE (SZ_4G + SZ_1G)
|
||||
|
||||
#endif /* __TORADEX_SMARC_IMX8MP_H */
|
||||
@@ -333,6 +333,30 @@ int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent,
|
||||
int uclass_get_device_by_driver(enum uclass_id id, const struct driver *drv,
|
||||
struct udevice **devp);
|
||||
|
||||
/**
|
||||
* uclass_get_device_by_endpoint() - Get a uclass device for a remote endpoint
|
||||
*
|
||||
* This searches through the parents of the specified remote endpoint
|
||||
* for the first device matching the uclass. Said otherwise, this helper
|
||||
* goes through the graph (endpoint) representation and searches for
|
||||
* matching devices. Endpoints can be subnodes of the "port" node or
|
||||
* subnodes of ports identified with a reg property, themselves in a
|
||||
* "ports" container.
|
||||
*
|
||||
* The device is probed to activate it ready for use.
|
||||
*
|
||||
* @class_id: uclass ID to look up
|
||||
* @dev: Device to start from
|
||||
* @port_idx: Index of the port to follow, -1 if there is a single 'port'
|
||||
* node without reg.
|
||||
* @ep_idx: Index of the endpoint to follow, -1 if there is a single 'endpoint'
|
||||
* node without reg.
|
||||
* @target: Returns pointer to the first device matching the expected uclass.
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
int uclass_get_device_by_endpoint(enum uclass_id class_id, struct udevice *dev,
|
||||
int port_idx, int ep_idx, struct udevice **target);
|
||||
|
||||
/**
|
||||
* uclass_first_device() - Get the first device in a uclass
|
||||
*
|
||||
|
||||
@@ -147,37 +147,81 @@ static inline int power_domain_free(struct power_domain *power_domain)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* power_domain_on - Enable power to a power domain.
|
||||
* power_domain_on_lowlevel - Enable power to a power domain (with refcounting)
|
||||
*
|
||||
* @power_domain: A power domain struct that was previously successfully
|
||||
* requested by power_domain_get().
|
||||
* Return: 0 if OK, or a negative error code.
|
||||
* Return: 0 if the transition has been performed correctly,
|
||||
* -EALREADY if the domain is already on,
|
||||
* a negative error code otherwise.
|
||||
*/
|
||||
#if CONFIG_IS_ENABLED(POWER_DOMAIN)
|
||||
int power_domain_on(struct power_domain *power_domain);
|
||||
int power_domain_on_lowlevel(struct power_domain *power_domain);
|
||||
#else
|
||||
static inline int power_domain_on(struct power_domain *power_domain)
|
||||
static inline int power_domain_on_lowlevel(struct power_domain *power_domain)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* power_domain_off - Disable power to a power domain.
|
||||
* power_domain_on - Enable power to a power domain (ignores the actual state
|
||||
* of the power domain)
|
||||
*
|
||||
* @power_domain: A power domain struct that was previously successfully
|
||||
* requested by power_domain_get().
|
||||
* Return: 0 if OK, or a negative error code.
|
||||
* Return: a negative error code upon error during the transition, 0 otherwise.
|
||||
*/
|
||||
static inline int power_domain_on(struct power_domain *power_domain)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = power_domain_on_lowlevel(power_domain);
|
||||
if (ret == -EALREADY)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* power_domain_off_lowlevel - Disable power to a power domain (with refcounting)
|
||||
*
|
||||
* @power_domain: A power domain struct that was previously successfully
|
||||
* requested by power_domain_get().
|
||||
* Return: 0 if the transition has been performed correctly,
|
||||
* -EALREADY if the domain is already off,
|
||||
* -EBUSY if another device is keeping the domain on (but the refcounter
|
||||
* is decremented),
|
||||
* a negative error code otherwise.
|
||||
*/
|
||||
#if CONFIG_IS_ENABLED(POWER_DOMAIN)
|
||||
int power_domain_off(struct power_domain *power_domain);
|
||||
int power_domain_off_lowlevel(struct power_domain *power_domain);
|
||||
#else
|
||||
static inline int power_domain_off(struct power_domain *power_domain)
|
||||
static inline int power_domain_off_lowlevel(struct power_domain *power_domain)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* power_domain_off - Disable power to a power domain (ignores the actual state
|
||||
* of the power domain)
|
||||
*
|
||||
* @power_domain: A power domain struct that was previously successfully
|
||||
* requested by power_domain_get().
|
||||
* Return: a negative error code upon error during the transition, 0 otherwise.
|
||||
*/
|
||||
static inline int power_domain_off(struct power_domain *power_domain)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = power_domain_off_lowlevel(power_domain);
|
||||
if (ret == -EALREADY || ret == -EBUSY)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* dev_power_domain_on - Enable power domains for a device .
|
||||
*
|
||||
|
||||
@@ -27,7 +27,7 @@ static int dm_test_power_domain(struct unit_test_state *uts)
|
||||
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "power-domain-test",
|
||||
&dev_test));
|
||||
ut_asserteq(1, sandbox_power_domain_query(dev_power_domain,
|
||||
ut_asserteq(0, sandbox_power_domain_query(dev_power_domain,
|
||||
TEST_POWER_DOMAIN));
|
||||
ut_assertok(sandbox_power_domain_test_get(dev_test));
|
||||
|
||||
|
||||
@@ -792,7 +792,7 @@ DM_TEST(dm_test_fdt_disable_enable_by_path, UTF_SCAN_PDATA | UTF_SCAN_FDT);
|
||||
/* Test a few uclass phandle functions */
|
||||
static int dm_test_fdt_phandle(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *back, *dev, *dev2;
|
||||
struct udevice *back, *dispc, *panel, *dev, *dev2;
|
||||
|
||||
ut_assertok(uclass_find_first_device(UCLASS_PANEL_BACKLIGHT, &back));
|
||||
ut_assertnonnull(back);
|
||||
@@ -807,6 +807,24 @@ static int dm_test_fdt_phandle(struct unit_test_state *uts)
|
||||
"power-supply", &dev2));
|
||||
ut_asserteq_ptr(dev, dev2);
|
||||
|
||||
/* Test uclass_get_device_by_endpoint() */
|
||||
ut_assertok(uclass_find_device_by_name(UCLASS_VIDEO_BRIDGE, "lvds-encoder", &dispc));
|
||||
ut_assertnonnull(dispc);
|
||||
ut_asserteq(0, device_active(dispc));
|
||||
ut_assertok(uclass_find_device_by_name(UCLASS_PANEL, "panel", &panel));
|
||||
ut_assertnonnull(panel);
|
||||
ut_asserteq(0, device_active(panel));
|
||||
|
||||
ut_asserteq(-ENODEV, uclass_get_device_by_endpoint(UCLASS_PANEL_BACKLIGHT, dispc, 1, -1, &dev));
|
||||
ut_asserteq(-EINVAL, uclass_get_device_by_endpoint(UCLASS_PANEL, dispc, 0, -1, &dev));
|
||||
ut_assertok(uclass_get_device_by_endpoint(UCLASS_PANEL, dispc, 1, -1, &dev));
|
||||
ut_asserteq_ptr(panel, dev);
|
||||
|
||||
ut_asserteq(-ENODEV, uclass_get_device_by_endpoint(UCLASS_PANEL_BACKLIGHT, panel, -1, -1, &dev2));
|
||||
ut_asserteq(-EINVAL, uclass_get_device_by_endpoint(UCLASS_VIDEO_BRIDGE, panel, 1, -1, &dev2));
|
||||
ut_assertok(uclass_get_device_by_endpoint(UCLASS_VIDEO_BRIDGE, panel, -1, -1, &dev2));
|
||||
ut_asserteq_ptr(dispc, dev2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_fdt_phandle, UTF_SCAN_PDATA | UTF_SCAN_FDT);
|
||||
|
||||
Reference in New Issue
Block a user