- Add Ethernet support for STM32MP1
- Add saveenv support for STM32MP1 - Add STM32MP1 Avenger96 board support - Add SPI driver suport for STM32MP1 - Add watchdog support for STM32MP1 - Update power supply check via USB TYPE-C for STM32MP1 discovery board -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJc+TqsAAoJEMrHeC97M/+miKwP/3OouX3slblEfUELRj/9qLlU ypdUDKDQupGSrTIyhJHFdGbA2ct/ERl4mH/kU8NNeCHVCsdvrrmuw+k4jfVZfIyi d9gWmU5WanNPzdWwdo0NrVNXjN5LPduxeUCYHdDEggDJuG3YL4LA9pPyrWpL8o8t tLPr8YMB1u5Ab8Vn/1A9lKvmw98V59LmWVxZh0AtAdOTvWgEZQe1R5Vex+MHacnK uR/Dm3ry5v7ZlR/kMZ0C+Ip1aw9GU4e+O+LCGlU4Jr0GV2XQOr4ehxWtN02nYubc sYXbkW7UArR0I0g8YPXPoBI9PToi57bHW/TXKoI8yDIll7vZ9PDjT/FbUJM9rv72 WU6T7+K2DeHflmp4NljiesD2rDnti0XSCbe4o5o/jD+YkzH6YoJbco4nsae7TBSM R3rgV7/+St7zC1IjFq0TUG+S9qSUmZqA4k66+j5/SS6pLQOW3dYemL0/up2cRX5w dx00JTQkHyh7Q/GfH8r7yZqIToW9djB9HeT88ovPUCh8rVfDqNn8/WKd2JAfkxda QiZDs49BMBsnWpK+vPqiq/suoJeSwDB70iMzrGgBg+mTd9eJcD0c5QBURYE0jm2H GqQ04WNi8sLzULhMqKbBdPZhBMzyNmDXF6MC+y/OcUM5k8z6tY8LDro3wgHXWVpX DLiFVbkHbLhlUJbeO8dD =2C9f -----END PGP SIGNATURE----- Merge tag 'u-boot-stm32-20190606' of https://github.com/pchotard/u-boot - Add Ethernet support for STM32MP1 - Add saveenv support for STM32MP1 - Add STM32MP1 Avenger96 board support - Add SPI driver suport for STM32MP1 - Add watchdog support for STM32MP1 - Update power supply check via USB TYPE-C for STM32MP1 discovery board
This commit is contained in:
commit
2702646bc0
@ -313,6 +313,8 @@ F: drivers/ram/stm32mp1/
|
||||
F: drivers/misc/stm32_rcc.c
|
||||
F: drivers/reset/stm32-reset.c
|
||||
F: drivers/spi/stm32_qspi.c
|
||||
F: drivers/spi/stm32_spi.c
|
||||
F: drivers/watchdog/stm32mp_wdt.c
|
||||
|
||||
ARM STM STV0991
|
||||
M: Vikas Manocha <vikas.manocha@st.com>
|
||||
|
@ -757,6 +757,7 @@ dtb-$(CONFIG_ARCH_STI) += stih410-b2260.dtb
|
||||
|
||||
dtb-$(CONFIG_TARGET_STM32MP1) += \
|
||||
stm32mp157a-dk1.dtb \
|
||||
stm32mp157a-avenger96.dtb \
|
||||
stm32mp157c-dk2.dtb \
|
||||
stm32mp157c-ed1.dtb \
|
||||
stm32mp157c-ev1.dtb
|
||||
|
@ -173,13 +173,18 @@
|
||||
<STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */
|
||||
<STM32_PINMUX('E', 2, AF11)>, /* ETH_RGMII_TXD3 */
|
||||
<STM32_PINMUX('B', 11, AF11)>, /* ETH_RGMII_TX_CTL */
|
||||
<STM32_PINMUX('A', 2, AF11)>, /* ETH_MDIO */
|
||||
<STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */
|
||||
bias-disable;
|
||||
drive-push-pull;
|
||||
slew-rate = <3>;
|
||||
slew-rate = <2>;
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('A', 2, AF11)>; /* ETH_MDIO */
|
||||
bias-disable;
|
||||
drive-push-pull;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
pins3 {
|
||||
pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */
|
||||
<STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */
|
||||
<STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */
|
||||
@ -210,6 +215,50 @@
|
||||
};
|
||||
};
|
||||
|
||||
fmc_pins_a: fmc-0 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('D', 4, AF12)>, /* FMC_NOE */
|
||||
<STM32_PINMUX('D', 5, AF12)>, /* FMC_NWE */
|
||||
<STM32_PINMUX('D', 11, AF12)>, /* FMC_A16_FMC_CLE */
|
||||
<STM32_PINMUX('D', 12, AF12)>, /* FMC_A17_FMC_ALE */
|
||||
<STM32_PINMUX('D', 14, AF12)>, /* FMC_D0 */
|
||||
<STM32_PINMUX('D', 15, AF12)>, /* FMC_D1 */
|
||||
<STM32_PINMUX('D', 0, AF12)>, /* FMC_D2 */
|
||||
<STM32_PINMUX('D', 1, AF12)>, /* FMC_D3 */
|
||||
<STM32_PINMUX('E', 7, AF12)>, /* FMC_D4 */
|
||||
<STM32_PINMUX('E', 8, AF12)>, /* FMC_D5 */
|
||||
<STM32_PINMUX('E', 9, AF12)>, /* FMC_D6 */
|
||||
<STM32_PINMUX('E', 10, AF12)>, /* FMC_D7 */
|
||||
<STM32_PINMUX('G', 9, AF12)>; /* FMC_NE2_FMC_NCE */
|
||||
bias-disable;
|
||||
drive-push-pull;
|
||||
slew-rate = <1>;
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('D', 6, AF12)>; /* FMC_NWAIT */
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
fmc_sleep_pins_a: fmc-sleep-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('D', 4, ANALOG)>, /* FMC_NOE */
|
||||
<STM32_PINMUX('D', 5, ANALOG)>, /* FMC_NWE */
|
||||
<STM32_PINMUX('D', 11, ANALOG)>, /* FMC_A16_FMC_CLE */
|
||||
<STM32_PINMUX('D', 12, ANALOG)>, /* FMC_A17_FMC_ALE */
|
||||
<STM32_PINMUX('D', 14, ANALOG)>, /* FMC_D0 */
|
||||
<STM32_PINMUX('D', 15, ANALOG)>, /* FMC_D1 */
|
||||
<STM32_PINMUX('D', 0, ANALOG)>, /* FMC_D2 */
|
||||
<STM32_PINMUX('D', 1, ANALOG)>, /* FMC_D3 */
|
||||
<STM32_PINMUX('E', 7, ANALOG)>, /* FMC_D4 */
|
||||
<STM32_PINMUX('E', 8, ANALOG)>, /* FMC_D5 */
|
||||
<STM32_PINMUX('E', 9, ANALOG)>, /* FMC_D6 */
|
||||
<STM32_PINMUX('E', 10, ANALOG)>, /* FMC_D7 */
|
||||
<STM32_PINMUX('D', 6, ANALOG)>, /* FMC_NWAIT */
|
||||
<STM32_PINMUX('G', 9, ANALOG)>; /* FMC_NE2_FMC_NCE */
|
||||
};
|
||||
};
|
||||
|
||||
i2c1_pins_a: i2c1-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */
|
||||
@ -220,6 +269,16 @@
|
||||
};
|
||||
};
|
||||
|
||||
i2c1_pins_b: i2c1-1 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('F', 14, AF5)>, /* I2C1_SCL */
|
||||
<STM32_PINMUX('F', 15, AF5)>; /* I2C1_SDA */
|
||||
bias-disable;
|
||||
drive-open-drain;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c2_pins_a: i2c2-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('H', 4, AF4)>, /* I2C2_SCL */
|
||||
@ -230,6 +289,16 @@
|
||||
};
|
||||
};
|
||||
|
||||
i2c2_pins_b: i2c2-1 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('Z', 0, AF3)>, /* I2C2_SCL */
|
||||
<STM32_PINMUX('H', 5, AF4)>; /* I2C2_SDA */
|
||||
bias-disable;
|
||||
drive-open-drain;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c5_pins_a: i2c5-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('A', 11, AF4)>, /* I2C5_SCL */
|
||||
@ -375,6 +444,21 @@
|
||||
};
|
||||
};
|
||||
|
||||
spi2_pins_a: spi2-0 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('B', 10, AF5)>, /* SPI2_SCK */
|
||||
<STM32_PINMUX('I', 0, AF5)>, /* SPI2_NSS */
|
||||
<STM32_PINMUX('I', 3, AF5)>; /* SPI2_MOSI */
|
||||
bias-disable;
|
||||
drive-push-pull;
|
||||
slew-rate = <3>;
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('I', 2, AF5)>; /* SPI2_MISO */
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
stusb1600_pins_a: stusb1600-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('I', 11, ANALOG)>;
|
||||
@ -395,6 +479,34 @@
|
||||
};
|
||||
};
|
||||
|
||||
uart4_pins_b: uart4-1 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('D', 1, AF8)>; /* UART4_TX */
|
||||
bias-disable;
|
||||
drive-push-pull;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
uart7_pins_a: uart7-0 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('E', 8, AF7)>; /* UART4_TX */
|
||||
bias-disable;
|
||||
drive-push-pull;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('E', 7, AF7)>, /* UART4_RX */
|
||||
<STM32_PINMUX('E', 10, AF7)>, /* UART4_CTS */
|
||||
<STM32_PINMUX('E', 9, AF7)>; /* UART4_RTS */
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
usbotg_hs_pins_a: usbotg_hs-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('A', 10, ANALOG)>; /* OTG_ID */
|
||||
|
@ -140,3 +140,7 @@
|
||||
compatible = "st,stm32-gpio";
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
&iwdg2 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
191
arch/arm/dts/stm32mp157a-avenger96-u-boot.dtsi
Normal file
191
arch/arm/dts/stm32mp157a-avenger96-u-boot.dtsi
Normal file
@ -0,0 +1,191 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
|
||||
/*
|
||||
* Copyright : STMicroelectronics 2018
|
||||
*
|
||||
* Copyright (C) Linaro Ltd 2019 - All Rights Reserved
|
||||
* Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
*/
|
||||
|
||||
#include <dt-bindings/clock/stm32mp1-clksrc.h>
|
||||
#include "stm32mp157-u-boot.dtsi"
|
||||
#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi"
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
mmc0 = &sdmmc1;
|
||||
mmc1 = &sdmmc2;
|
||||
usb0 = &usbotg_hs;
|
||||
};
|
||||
|
||||
config {
|
||||
u-boot,boot-led = "led1";
|
||||
u-boot,error-led = "led4";
|
||||
};
|
||||
};
|
||||
|
||||
&i2c4 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
&i2c4_pins_a {
|
||||
u-boot,dm-pre-reloc;
|
||||
pins {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
};
|
||||
|
||||
&pmic {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
&rcc {
|
||||
st,clksrc = <
|
||||
CLK_MPU_PLL1P
|
||||
CLK_AXI_PLL2P
|
||||
CLK_MCU_PLL3P
|
||||
CLK_PLL12_HSE
|
||||
CLK_PLL3_HSE
|
||||
CLK_PLL4_HSE
|
||||
CLK_RTC_LSE
|
||||
CLK_MCO1_DISABLED
|
||||
CLK_MCO2_DISABLED
|
||||
>;
|
||||
|
||||
st,clkdiv = <
|
||||
1 /*MPU*/
|
||||
0 /*AXI*/
|
||||
0 /*MCU*/
|
||||
1 /*APB1*/
|
||||
1 /*APB2*/
|
||||
1 /*APB3*/
|
||||
1 /*APB4*/
|
||||
2 /*APB5*/
|
||||
23 /*RTC*/
|
||||
0 /*MCO1*/
|
||||
0 /*MCO2*/
|
||||
>;
|
||||
|
||||
st,pkcs = <
|
||||
CLK_CKPER_HSE
|
||||
CLK_FMC_ACLK
|
||||
CLK_QSPI_ACLK
|
||||
CLK_ETH_DISABLED
|
||||
CLK_SDMMC12_PLL4P
|
||||
CLK_DSI_DSIPLL
|
||||
CLK_STGEN_HSE
|
||||
CLK_USBPHY_HSE
|
||||
CLK_SPI2S1_PLL3Q
|
||||
CLK_SPI2S23_PLL3Q
|
||||
CLK_SPI45_HSI
|
||||
CLK_SPI6_HSI
|
||||
CLK_I2C46_HSI
|
||||
CLK_SDMMC3_PLL4P
|
||||
CLK_USBO_USBPHY
|
||||
CLK_ADC_CKPER
|
||||
CLK_CEC_LSE
|
||||
CLK_I2C12_HSI
|
||||
CLK_I2C35_HSI
|
||||
CLK_UART1_HSI
|
||||
CLK_UART24_HSI
|
||||
CLK_UART35_HSI
|
||||
CLK_UART6_HSI
|
||||
CLK_UART78_HSI
|
||||
CLK_SPDIF_PLL4P
|
||||
CLK_FDCAN_PLL4Q
|
||||
CLK_SAI1_PLL3Q
|
||||
CLK_SAI2_PLL3Q
|
||||
CLK_SAI3_PLL3Q
|
||||
CLK_SAI4_PLL3Q
|
||||
CLK_RNG1_LSI
|
||||
CLK_RNG2_LSI
|
||||
CLK_LPTIM1_PCLK1
|
||||
CLK_LPTIM23_PCLK3
|
||||
CLK_LPTIM45_LSE
|
||||
>;
|
||||
|
||||
/* VCO = 1300.0 MHz => P = 650 (CPU) */
|
||||
pll1: st,pll@0 {
|
||||
cfg = < 2 80 0 0 0 PQR(1,0,0) >;
|
||||
frac = < 0x800 >;
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */
|
||||
pll2: st,pll@1 {
|
||||
cfg = < 2 65 1 0 0 PQR(1,1,1) >;
|
||||
frac = < 0x1400 >;
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
/* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
|
||||
pll3: st,pll@2 {
|
||||
cfg = < 1 33 1 16 36 PQR(1,1,1) >;
|
||||
frac = < 0x1a04 >;
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
/* VCO = 480.0 MHz => P = 120, Q = 40, R = 96 */
|
||||
pll4: st,pll@3 {
|
||||
cfg = < 1 39 3 11 4 PQR(1,1,1) >;
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
};
|
||||
|
||||
&sdmmc1 {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&sdmmc1_b4_pins_a {
|
||||
u-boot,dm-spl;
|
||||
pins {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
};
|
||||
|
||||
&sdmmc1_dir_pins_a {
|
||||
u-boot,dm-spl;
|
||||
pins {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
};
|
||||
|
||||
&sdmmc2 {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&sdmmc2_b4_pins_a {
|
||||
u-boot,dm-spl;
|
||||
pins {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
};
|
||||
|
||||
&sdmmc2_d47_pins_a {
|
||||
u-boot,dm-spl;
|
||||
pins {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
};
|
||||
|
||||
&uart4 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
&uart4_pins_b {
|
||||
u-boot,dm-pre-reloc;
|
||||
pins1 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
pins2 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
};
|
||||
|
||||
&usbotg_hs {
|
||||
u-boot,force-b-session-valid;
|
||||
hnp-srp-disable;
|
||||
};
|
||||
|
||||
&v3v3 {
|
||||
regulator-always-on;
|
||||
};
|
362
arch/arm/dts/stm32mp157a-avenger96.dts
Normal file
362
arch/arm/dts/stm32mp157a-avenger96.dts
Normal file
@ -0,0 +1,362 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
|
||||
/*
|
||||
* Copyright (C) STMicroelectronics 2019 - All Rights Reserved
|
||||
* Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
|
||||
*
|
||||
* Copyright (C) Linaro Ltd 2019 - All Rights Reserved
|
||||
* Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "stm32mp157c.dtsi"
|
||||
#include "stm32mp157-pinctrl.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/mfd/st,stpmic1.h>
|
||||
|
||||
/ {
|
||||
model = "Arrow Electronics STM32MP157A Avenger96 board";
|
||||
compatible = "st,stm32mp157a-avenger96", "st,stm32mp157";
|
||||
|
||||
aliases {
|
||||
ethernet0 = ðernet0;
|
||||
serial0 = &uart4;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
memory@c0000000 {
|
||||
reg = <0xc0000000 0x40000000>;
|
||||
};
|
||||
|
||||
led {
|
||||
compatible = "gpio-leds";
|
||||
led1 {
|
||||
label = "green:user1";
|
||||
gpios = <&gpioz 7 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
led2 {
|
||||
label = "green:user2";
|
||||
gpios = <&gpiof 3 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "mmc0";
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
led3 {
|
||||
label = "green:user3";
|
||||
gpios = <&gpiog 0 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "mmc1";
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
led4 {
|
||||
label = "green:user3";
|
||||
gpios = <&gpiog 1 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "none";
|
||||
default-state = "off";
|
||||
panic-indicator;
|
||||
};
|
||||
|
||||
led5 {
|
||||
label = "yellow:wifi";
|
||||
gpios = <&gpioz 3 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "phy0tx";
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
led6 {
|
||||
label = "blue:bt";
|
||||
gpios = <&gpioz 6 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "bluetooth-power";
|
||||
default-state = "off";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
status = "okay";
|
||||
pinctrl-0 = <ðernet0_rgmii_pins_a>;
|
||||
pinctrl-1 = <ðernet0_rgmii_pins_sleep_a>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
phy-mode = "rgmii";
|
||||
max-speed = <1000>;
|
||||
phy-handle = <&phy0>;
|
||||
|
||||
mdio0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "snps,dwmac-mdio";
|
||||
phy0: ethernet-phy@7 {
|
||||
reg = <7>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1_pins_b>;
|
||||
i2c-scl-rising-time-ns = <185>;
|
||||
i2c-scl-falling-time-ns = <20>;
|
||||
status = "okay";
|
||||
/delete-property/dmas;
|
||||
/delete-property/dma-names;
|
||||
};
|
||||
|
||||
&i2c2 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c2_pins_b>;
|
||||
i2c-scl-rising-time-ns = <185>;
|
||||
i2c-scl-falling-time-ns = <20>;
|
||||
status = "okay";
|
||||
/delete-property/dmas;
|
||||
/delete-property/dma-names;
|
||||
};
|
||||
|
||||
&i2c4 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c4_pins_a>;
|
||||
i2c-scl-rising-time-ns = <185>;
|
||||
i2c-scl-falling-time-ns = <20>;
|
||||
status = "okay";
|
||||
/delete-property/dmas;
|
||||
/delete-property/dma-names;
|
||||
|
||||
pmic: stpmic@33 {
|
||||
compatible = "st,stpmic1";
|
||||
reg = <0x33>;
|
||||
interrupts-extended = <&exti 55 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
status = "okay";
|
||||
|
||||
st,main-control-register = <0x04>;
|
||||
st,vin-control-register = <0xc0>;
|
||||
st,usb-control-register = <0x30>;
|
||||
|
||||
regulators {
|
||||
compatible = "st,stpmic1-regulators";
|
||||
|
||||
ldo1-supply = <&v3v3>;
|
||||
ldo2-supply = <&v3v3>;
|
||||
ldo3-supply = <&vdd_ddr>;
|
||||
ldo5-supply = <&v3v3>;
|
||||
ldo6-supply = <&v3v3>;
|
||||
pwr_sw1-supply = <&bst_out>;
|
||||
pwr_sw2-supply = <&bst_out>;
|
||||
|
||||
vddcore: buck1 {
|
||||
regulator-name = "vddcore";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-always-on;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-over-current-protection;
|
||||
};
|
||||
|
||||
vdd_ddr: buck2 {
|
||||
regulator-name = "vdd_ddr";
|
||||
regulator-min-microvolt = <1350000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-always-on;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-over-current-protection;
|
||||
};
|
||||
|
||||
vdd: buck3 {
|
||||
regulator-name = "vdd";
|
||||
regulator-min-microvolt = <2500000>;
|
||||
regulator-max-microvolt = <2500000>;
|
||||
regulator-always-on;
|
||||
st,mask_reset;
|
||||
regulator-initial-mode = <8>;
|
||||
regulator-over-current-protection;
|
||||
};
|
||||
|
||||
v3v3: buck4 {
|
||||
regulator-name = "v3v3";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
regulator-over-current-protection;
|
||||
regulator-initial-mode = <8>;
|
||||
};
|
||||
|
||||
vdda: ldo1 {
|
||||
regulator-name = "vdda";
|
||||
regulator-min-microvolt = <2900000>;
|
||||
regulator-max-microvolt = <2900000>;
|
||||
interrupts = <IT_CURLIM_LDO1 0>;
|
||||
interrupt-parent = <&pmic>;
|
||||
};
|
||||
|
||||
v2v8: ldo2 {
|
||||
regulator-name = "v2v8";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
interrupts = <IT_CURLIM_LDO2 0>;
|
||||
interrupt-parent = <&pmic>;
|
||||
};
|
||||
|
||||
vtt_ddr: ldo3 {
|
||||
regulator-name = "vtt_ddr";
|
||||
regulator-min-microvolt = <0000000>;
|
||||
regulator-max-microvolt = <1000000>;
|
||||
regulator-always-on;
|
||||
regulator-over-current-protection;
|
||||
};
|
||||
|
||||
vdd_usb: ldo4 {
|
||||
regulator-name = "vdd_usb";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
interrupts = <IT_CURLIM_LDO4 0>;
|
||||
interrupt-parent = <&pmic>;
|
||||
};
|
||||
|
||||
vdd_sd: ldo5 {
|
||||
regulator-name = "vdd_sd";
|
||||
regulator-min-microvolt = <2900000>;
|
||||
regulator-max-microvolt = <2900000>;
|
||||
interrupts = <IT_CURLIM_LDO5 0>;
|
||||
interrupt-parent = <&pmic>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
v1v8: ldo6 {
|
||||
regulator-name = "v1v8";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
interrupts = <IT_CURLIM_LDO6 0>;
|
||||
interrupt-parent = <&pmic>;
|
||||
};
|
||||
|
||||
vref_ddr: vref_ddr {
|
||||
regulator-name = "vref_ddr";
|
||||
regulator-always-on;
|
||||
regulator-over-current-protection;
|
||||
};
|
||||
|
||||
bst_out: boost {
|
||||
regulator-name = "bst_out";
|
||||
interrupts = <IT_OCP_BOOST 0>;
|
||||
interrupt-parent = <&pmic>;
|
||||
};
|
||||
|
||||
vbus_otg: pwr_sw1 {
|
||||
regulator-name = "vbus_otg";
|
||||
interrupts = <IT_OCP_OTG 0>;
|
||||
interrupt-parent = <&pmic>;
|
||||
regulator-active-discharge;
|
||||
};
|
||||
|
||||
vbus_sw: pwr_sw2 {
|
||||
regulator-name = "vbus_sw";
|
||||
interrupts = <IT_OCP_SWOUT 0>;
|
||||
interrupt-parent = <&pmic>;
|
||||
regulator-active-discharge;
|
||||
};
|
||||
};
|
||||
|
||||
onkey {
|
||||
compatible = "st,stpmic1-onkey";
|
||||
interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 1>;
|
||||
interrupt-names = "onkey-falling", "onkey-rising";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
watchdog {
|
||||
compatible = "st,stpmic1-wdt";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&iwdg2 {
|
||||
timeout-sec = <32>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pwr {
|
||||
pwr-supply = <&vdd>;
|
||||
};
|
||||
|
||||
&rng1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rtc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdmmc1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
|
||||
broken-cd;
|
||||
st,sig-dir;
|
||||
st,neg-edge;
|
||||
st,use-ckin;
|
||||
bus-width = <4>;
|
||||
vmmc-supply = <&vdd_sd>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdmmc2 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
|
||||
non-removable;
|
||||
no-sd;
|
||||
no-sdio;
|
||||
st,neg-edge;
|
||||
bus-width = <8>;
|
||||
vmmc-supply = <&v3v3>;
|
||||
mmc-ddr-3_3v;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spi2 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spi2_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart4 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart4_pins_b>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart7 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart7_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usbh_ehci {
|
||||
phys = <&usbphyc_port0>;
|
||||
phy-names = "usb";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usbotg_hs {
|
||||
dr_mode = "peripheral";
|
||||
phys = <&usbphyc_port1 0>;
|
||||
phy-names = "usb2-phy";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usbphyc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usbphyc_port0 {
|
||||
phy-supply = <&vdd_usb>;
|
||||
};
|
||||
|
||||
&usbphyc_port1 {
|
||||
phy-supply = <&vdd_usb>;
|
||||
};
|
@ -78,7 +78,7 @@
|
||||
pinctrl-0 = <ðernet0_rgmii_pins_a>;
|
||||
pinctrl-1 = <ðernet0_rgmii_pins_sleep_a>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
phy-mode = "rgmii";
|
||||
phy-mode = "rgmii-id";
|
||||
max-speed = <1000>;
|
||||
phy-handle = <&phy0>;
|
||||
|
||||
@ -92,6 +92,22 @@
|
||||
};
|
||||
};
|
||||
|
||||
&fmc {
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&fmc_pins_a>;
|
||||
pinctrl-1 = <&fmc_sleep_pins_a>;
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
nand: nand@0 {
|
||||
reg = <0>;
|
||||
nand-on-flash-bbt;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c2 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c2_pins_a>;
|
||||
|
@ -1033,6 +1033,21 @@
|
||||
dma-requests = <48>;
|
||||
};
|
||||
|
||||
fmc: nand-controller@58002000 {
|
||||
compatible = "st,stm32mp15-fmc2";
|
||||
reg = <0x58002000 0x1000>,
|
||||
<0x80000000 0x1000>,
|
||||
<0x88010000 0x1000>,
|
||||
<0x88020000 0x1000>,
|
||||
<0x81000000 0x1000>,
|
||||
<0x89010000 0x1000>,
|
||||
<0x89020000 0x1000>;
|
||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc FMC_K>;
|
||||
resets = <&rcc FMC_R>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
qspi: spi@58003000 {
|
||||
compatible = "st,stm32f469-qspi";
|
||||
reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
|
||||
@ -1087,21 +1102,25 @@
|
||||
compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";
|
||||
reg = <0x5800a000 0x2000>;
|
||||
reg-names = "stmmaceth";
|
||||
interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "macirq";
|
||||
interrupts-extended =
|
||||
<&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<&intc GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<&exti 70 1>;
|
||||
interrupt-names = "macirq",
|
||||
"eth_wake_irq",
|
||||
"stm32_pwr_wakeup";
|
||||
clock-names = "stmmaceth",
|
||||
"mac-clk-tx",
|
||||
"mac-clk-rx",
|
||||
"ethstp",
|
||||
"syscfg-clk";
|
||||
"ethstp";
|
||||
clocks = <&rcc ETHMAC>,
|
||||
<&rcc ETHTX>,
|
||||
<&rcc ETHRX>,
|
||||
<&rcc ETHSTP>,
|
||||
<&rcc SYSCFG>;
|
||||
<&rcc ETHSTP>;
|
||||
st,syscon = <&syscfg 0x4>;
|
||||
snps,mixed-burst;
|
||||
snps,pbl = <2>;
|
||||
snps,en-tx-lpi-clockgating;
|
||||
snps,axi-config = <&stmmac_axi_config_0>;
|
||||
snps,tso;
|
||||
status = "disabled";
|
||||
|
@ -17,6 +17,7 @@ config SPL
|
||||
select SPL_DM_RESET
|
||||
select SPL_SERIAL_SUPPORT
|
||||
select SPL_SYSCON
|
||||
select SPL_WATCHDOG_SUPPORT
|
||||
imply BOOTSTAGE_STASH if SPL_BOOTSTAGE
|
||||
imply SPL_BOOTSTAGE if BOOTSTAGE
|
||||
imply SPL_DISPLAY_PRINT
|
||||
@ -29,7 +30,7 @@ config SYS_MALLOC_LEN
|
||||
default 0x2000000
|
||||
|
||||
config ENV_SIZE
|
||||
default 0x1000
|
||||
default 0x2000
|
||||
|
||||
config TARGET_STM32MP1
|
||||
bool "Support stm32mp1xx"
|
||||
|
@ -481,7 +481,7 @@ static int setup_mac_address(void)
|
||||
enetaddr[i] = ((uint8_t *)&otp)[i];
|
||||
|
||||
if (!is_valid_ethaddr(enetaddr)) {
|
||||
pr_err("invalid MAC address in OTP %pM", enetaddr);
|
||||
pr_err("invalid MAC address in OTP %pM\n", enetaddr);
|
||||
return -EINVAL;
|
||||
}
|
||||
pr_debug("OTP MAC address = %pM\n", enetaddr);
|
||||
|
@ -37,6 +37,7 @@ Currently the following boards are supported:
|
||||
+ stm32mp157c-ed1
|
||||
+ stm32mp157a-dk1
|
||||
+ stm32mp157c-dk2
|
||||
+ stm32mp157a-avenger96
|
||||
|
||||
3. Boot Sequences
|
||||
=================
|
||||
@ -84,6 +85,9 @@ the supported device trees for stm32mp157 are:
|
||||
+ dk2: Discovery board = dk1 with a BT/WiFI combo and a DSI panel
|
||||
dts: stm32mp157c-dk2
|
||||
|
||||
+ avenger96: Avenger96 board from Arrow Electronics
|
||||
dts: stm32mp157a-avenger96
|
||||
|
||||
5. Build Procedure
|
||||
==================
|
||||
|
||||
@ -140,6 +144,11 @@ the supported device trees for stm32mp157 are:
|
||||
# make stm32mp15_basic_defconfig
|
||||
# make DEVICE_TREE=stm32mp157c-dk2 all
|
||||
|
||||
d) basic boot on avenger96
|
||||
# export KBUILD_OUTPUT=stm32mp15_basic
|
||||
# make stm32mp15_basic_defconfig
|
||||
# make DEVICE_TREE=stm32mp157a-avenger96 all
|
||||
|
||||
6. Output files
|
||||
|
||||
BootRom and TF-A expect binaries with STM32 image header
|
||||
@ -182,6 +191,20 @@ You can select the boot mode, on the board ed1 with the switch SW1
|
||||
SD-Card 1 1
|
||||
Recovery 0 0
|
||||
|
||||
- Boot mode of Avenger96 can be selected using switch S3
|
||||
|
||||
-----------------------------------
|
||||
Boot Mode BOOT2 BOOT1 BOOT0
|
||||
-----------------------------------
|
||||
Recovery 0 0 0
|
||||
NOR 0 0 1
|
||||
SD-Card 1 0 1
|
||||
eMMC 0 1 0
|
||||
NAND 0 1 1
|
||||
Reserved 1 0 0
|
||||
Recovery 1 1 0
|
||||
SD-Card 1 1 1
|
||||
|
||||
Recovery is a boot from serial link (UART/USB) and it is used with
|
||||
STM32CubeProgrammer tool to load executable in RAM and to update the flash
|
||||
devices available on the board (NOR/NAND/eMMC/SDCARD).
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <config.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <environment.h>
|
||||
#include <g_dnl.h>
|
||||
#include <generic-phy.h>
|
||||
#include <i2c.h>
|
||||
@ -19,6 +20,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/stm32.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <power/regulator.h>
|
||||
#include <usb/dwc2_udc.h>
|
||||
|
||||
@ -51,18 +53,19 @@
|
||||
#define SYSCFG_PMCSETR_ETH_SELMII BIT(20)
|
||||
|
||||
#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21)
|
||||
#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII (0 << 21)
|
||||
#define SYSCFG_PMCSETR_ETH_SEL_RGMII (1 << 21)
|
||||
#define SYSCFG_PMCSETR_ETH_SEL_RMII (4 << 21)
|
||||
#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0
|
||||
#define SYSCFG_PMCSETR_ETH_SEL_RGMII BIT(21)
|
||||
#define SYSCFG_PMCSETR_ETH_SEL_RMII BIT(23)
|
||||
|
||||
/*
|
||||
* Get a global data pointer
|
||||
*/
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define USB_LOW_THRESHOLD_UV 200000
|
||||
#define USB_WARNING_LOW_THRESHOLD_UV 660000
|
||||
#define USB_START_LOW_THRESHOLD_UV 1230000
|
||||
#define USB_START_HIGH_THRESHOLD_UV 2100000
|
||||
#define USB_START_HIGH_THRESHOLD_UV 2150000
|
||||
|
||||
int checkboard(void)
|
||||
{
|
||||
@ -263,9 +266,10 @@ static int board_check_usb_power(void)
|
||||
ofnode node;
|
||||
unsigned int raw;
|
||||
int max_uV = 0;
|
||||
int min_uV = USB_START_HIGH_THRESHOLD_UV;
|
||||
int ret, uV, adc_count;
|
||||
u8 i, nb_blink;
|
||||
|
||||
u32 nb_blink;
|
||||
u8 i;
|
||||
node = ofnode_path("/config");
|
||||
if (!ofnode_valid(node)) {
|
||||
debug("%s: no /config node?\n", __func__);
|
||||
@ -317,6 +321,8 @@ static int board_check_usb_power(void)
|
||||
if (!adc_raw_to_uV(adc, raw, &uV)) {
|
||||
if (uV > max_uV)
|
||||
max_uV = uV;
|
||||
if (uV < min_uV)
|
||||
min_uV = uV;
|
||||
pr_debug("%s: %s[%02d] = %u, %d uV\n", __func__,
|
||||
adc->name, adc_args.args[0], raw, uV);
|
||||
} else {
|
||||
@ -331,27 +337,66 @@ static int board_check_usb_power(void)
|
||||
* continue.
|
||||
*/
|
||||
if (max_uV > USB_START_LOW_THRESHOLD_UV &&
|
||||
max_uV < USB_START_HIGH_THRESHOLD_UV)
|
||||
max_uV <= USB_START_HIGH_THRESHOLD_UV &&
|
||||
min_uV <= USB_LOW_THRESHOLD_UV)
|
||||
return 0;
|
||||
|
||||
/* Display warning message and make u-boot,error-led blinking */
|
||||
pr_err("\n*******************************************\n");
|
||||
pr_err("****************************************************\n");
|
||||
|
||||
if (max_uV < USB_WARNING_LOW_THRESHOLD_UV) {
|
||||
pr_err("* WARNING 500mA power supply detected *\n");
|
||||
/*
|
||||
* If highest and lowest value are either both below
|
||||
* USB_LOW_THRESHOLD_UV or both above USB_LOW_THRESHOLD_UV, that
|
||||
* means USB TYPE-C is in unattached mode, this is an issue, make
|
||||
* u-boot,error-led blinking and stop boot process.
|
||||
*/
|
||||
if ((max_uV > USB_LOW_THRESHOLD_UV &&
|
||||
min_uV > USB_LOW_THRESHOLD_UV) ||
|
||||
(max_uV <= USB_LOW_THRESHOLD_UV &&
|
||||
min_uV <= USB_LOW_THRESHOLD_UV)) {
|
||||
pr_err("* ERROR USB TYPE-C connection in unattached mode *\n");
|
||||
pr_err("* Check that USB TYPE-C cable is correctly plugged *\n");
|
||||
/* with 125ms interval, led will blink for 17.02 years ....*/
|
||||
nb_blink = U32_MAX;
|
||||
}
|
||||
|
||||
if (max_uV > USB_LOW_THRESHOLD_UV &&
|
||||
max_uV <= USB_WARNING_LOW_THRESHOLD_UV &&
|
||||
min_uV <= USB_LOW_THRESHOLD_UV) {
|
||||
pr_err("* WARNING 500mA power supply detected *\n");
|
||||
nb_blink = 2;
|
||||
} else {
|
||||
pr_err("* WARNING 1.5A power supply detected *\n");
|
||||
}
|
||||
|
||||
if (max_uV > USB_WARNING_LOW_THRESHOLD_UV &&
|
||||
max_uV <= USB_START_LOW_THRESHOLD_UV &&
|
||||
min_uV <= USB_LOW_THRESHOLD_UV) {
|
||||
pr_err("* WARNING 1.5mA power supply detected *\n");
|
||||
nb_blink = 3;
|
||||
}
|
||||
|
||||
pr_err("* Current too low, use a 3A power supply! *\n");
|
||||
pr_err("*******************************************\n\n");
|
||||
/*
|
||||
* If highest value is above 2.15 Volts that means that the USB TypeC
|
||||
* supplies more than 3 Amp, this is not compliant with TypeC specification
|
||||
*/
|
||||
if (max_uV > USB_START_HIGH_THRESHOLD_UV) {
|
||||
pr_err("* USB TYPE-C charger not compliant with *\n");
|
||||
pr_err("* specification *\n");
|
||||
pr_err("****************************************************\n\n");
|
||||
/* with 125ms interval, led will blink for 17.02 years ....*/
|
||||
nb_blink = U32_MAX;
|
||||
} else {
|
||||
pr_err("* Current too low, use a 3A power supply! *\n");
|
||||
pr_err("****************************************************\n\n");
|
||||
}
|
||||
|
||||
ret = get_led(&led, "u-boot,error-led");
|
||||
if (ret)
|
||||
if (ret) {
|
||||
/* in unattached case, the boot process must be stopped */
|
||||
if (nb_blink == U32_MAX)
|
||||
hang();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* make u-boot,error-led blinking */
|
||||
for (i = 0; i < nb_blink * 2; i++) {
|
||||
led_set_state(led, LEDST_TOGGLE);
|
||||
mdelay(125);
|
||||
@ -504,3 +549,199 @@ void board_quiesce_devices(void)
|
||||
{
|
||||
setup_led(LEDST_OFF);
|
||||
}
|
||||
|
||||
/* board interface eth init */
|
||||
/* this is a weak define that we are overriding */
|
||||
int board_interface_eth_init(phy_interface_t interface_type,
|
||||
bool eth_clk_sel_reg, bool eth_ref_clk_sel_reg)
|
||||
{
|
||||
u8 *syscfg;
|
||||
u32 value;
|
||||
|
||||
syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
|
||||
|
||||
if (!syscfg)
|
||||
return -ENODEV;
|
||||
|
||||
switch (interface_type) {
|
||||
case PHY_INTERFACE_MODE_MII:
|
||||
value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
|
||||
SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
|
||||
debug("%s: PHY_INTERFACE_MODE_MII\n", __func__);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_GMII:
|
||||
if (eth_clk_sel_reg)
|
||||
value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
|
||||
SYSCFG_PMCSETR_ETH_CLK_SEL;
|
||||
else
|
||||
value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII;
|
||||
debug("%s: PHY_INTERFACE_MODE_GMII\n", __func__);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RMII:
|
||||
if (eth_ref_clk_sel_reg)
|
||||
value = SYSCFG_PMCSETR_ETH_SEL_RMII |
|
||||
SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
|
||||
else
|
||||
value = SYSCFG_PMCSETR_ETH_SEL_RMII;
|
||||
debug("%s: PHY_INTERFACE_MODE_RMII\n", __func__);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
if (eth_clk_sel_reg)
|
||||
value = SYSCFG_PMCSETR_ETH_SEL_RGMII |
|
||||
SYSCFG_PMCSETR_ETH_CLK_SEL;
|
||||
else
|
||||
value = SYSCFG_PMCSETR_ETH_SEL_RGMII;
|
||||
debug("%s: PHY_INTERFACE_MODE_RGMII\n", __func__);
|
||||
break;
|
||||
default:
|
||||
debug("%s: Do not manage %d interface\n",
|
||||
__func__, interface_type);
|
||||
/* Do not manage others interfaces */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* clear and set ETH configuration bits */
|
||||
writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII |
|
||||
SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL,
|
||||
syscfg + SYSCFG_PMCCLRR);
|
||||
writel(value, syscfg + SYSCFG_PMCSETR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum env_location env_get_location(enum env_operation op, int prio)
|
||||
{
|
||||
u32 bootmode = get_bootmode();
|
||||
|
||||
if (prio)
|
||||
return ENVL_UNKNOWN;
|
||||
|
||||
switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
|
||||
#ifdef CONFIG_ENV_IS_IN_EXT4
|
||||
case BOOT_FLASH_SD:
|
||||
case BOOT_FLASH_EMMC:
|
||||
return ENVL_EXT4;
|
||||
#endif
|
||||
#ifdef CONFIG_ENV_IS_IN_UBI
|
||||
case BOOT_FLASH_NAND:
|
||||
return ENVL_UBI;
|
||||
#endif
|
||||
#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
|
||||
case BOOT_FLASH_NOR:
|
||||
return ENVL_SPI_FLASH;
|
||||
#endif
|
||||
default:
|
||||
return ENVL_NOWHERE;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ENV_IS_IN_EXT4)
|
||||
const char *env_ext4_get_intf(void)
|
||||
{
|
||||
u32 bootmode = get_bootmode();
|
||||
|
||||
switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
|
||||
case BOOT_FLASH_SD:
|
||||
case BOOT_FLASH_EMMC:
|
||||
return "mmc";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
const char *env_ext4_get_dev_part(void)
|
||||
{
|
||||
static char *const dev_part[] = {"0:auto", "1:auto", "2:auto"};
|
||||
u32 bootmode = get_bootmode();
|
||||
|
||||
return dev_part[(bootmode & TAMP_BOOT_INSTANCE_MASK) - 1];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_MTDPARTS_RUNTIME
|
||||
|
||||
#define MTDPARTS_LEN 256
|
||||
#define MTDIDS_LEN 128
|
||||
|
||||
/**
|
||||
* The mtdparts_nand0 and mtdparts_nor0 variable tends to be long.
|
||||
* If we need to access it before the env is relocated, then we need
|
||||
* to use our own stack buffer. gd->env_buf will be too small.
|
||||
*
|
||||
* @param buf temporary buffer pointer MTDPARTS_LEN long
|
||||
* @return mtdparts variable string, NULL if not found
|
||||
*/
|
||||
static const char *env_get_mtdparts(const char *str, char *buf)
|
||||
{
|
||||
if (gd->flags & GD_FLG_ENV_READY)
|
||||
return env_get(str);
|
||||
if (env_get_f(str, buf, MTDPARTS_LEN) != -1)
|
||||
return buf;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* update the variables "mtdids" and "mtdparts" with content of mtdparts_<dev>
|
||||
*/
|
||||
static void board_get_mtdparts(const char *dev,
|
||||
char *mtdids,
|
||||
char *mtdparts)
|
||||
{
|
||||
char env_name[32] = "mtdparts_";
|
||||
char tmp_mtdparts[MTDPARTS_LEN];
|
||||
const char *tmp;
|
||||
|
||||
/* name of env variable to read = mtdparts_<dev> */
|
||||
strcat(env_name, dev);
|
||||
tmp = env_get_mtdparts(env_name, tmp_mtdparts);
|
||||
if (tmp) {
|
||||
/* mtdids: "<dev>=<dev>, ...." */
|
||||
if (mtdids[0] != '\0')
|
||||
strcat(mtdids, ",");
|
||||
strcat(mtdids, dev);
|
||||
strcat(mtdids, "=");
|
||||
strcat(mtdids, dev);
|
||||
|
||||
/* mtdparts: "mtdparts=<dev>:<mtdparts_<dev>>;..." */
|
||||
if (mtdparts[0] != '\0')
|
||||
strncat(mtdparts, ";", MTDPARTS_LEN);
|
||||
else
|
||||
strcat(mtdparts, "mtdparts=");
|
||||
strncat(mtdparts, dev, MTDPARTS_LEN);
|
||||
strncat(mtdparts, ":", MTDPARTS_LEN);
|
||||
strncat(mtdparts, tmp, MTDPARTS_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
void board_mtdparts_default(const char **mtdids, const char **mtdparts)
|
||||
{
|
||||
struct udevice *dev;
|
||||
static char parts[2 * MTDPARTS_LEN + 1];
|
||||
static char ids[MTDIDS_LEN + 1];
|
||||
static bool mtd_initialized;
|
||||
|
||||
if (mtd_initialized) {
|
||||
*mtdids = ids;
|
||||
*mtdparts = parts;
|
||||
return;
|
||||
}
|
||||
|
||||
memset(parts, 0, sizeof(parts));
|
||||
memset(ids, 0, sizeof(ids));
|
||||
|
||||
if (!uclass_get_device(UCLASS_MTD, 0, &dev))
|
||||
board_get_mtdparts("nand0", ids, parts);
|
||||
|
||||
if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev))
|
||||
board_get_mtdparts("nor0", ids, parts);
|
||||
|
||||
mtd_initialized = true;
|
||||
*mtdids = ids;
|
||||
*mtdparts = parts;
|
||||
debug("%s:mtdids=%s & mtdparts=%s\n", __func__, ids, parts);
|
||||
}
|
||||
#endif
|
||||
|
36
cmd/nvedit.c
36
cmd/nvedit.c
@ -39,18 +39,24 @@
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if !defined(CONFIG_ENV_IS_IN_EEPROM) && \
|
||||
!defined(CONFIG_ENV_IS_IN_FLASH) && \
|
||||
!defined(CONFIG_ENV_IS_IN_MMC) && \
|
||||
!defined(CONFIG_ENV_IS_IN_FAT) && \
|
||||
!defined(CONFIG_ENV_IS_IN_EXT4) && \
|
||||
!defined(CONFIG_ENV_IS_IN_NAND) && \
|
||||
!defined(CONFIG_ENV_IS_IN_NVRAM) && \
|
||||
!defined(CONFIG_ENV_IS_IN_ONENAND) && \
|
||||
!defined(CONFIG_ENV_IS_IN_SATA) && \
|
||||
!defined(CONFIG_ENV_IS_IN_SPI_FLASH) && \
|
||||
!defined(CONFIG_ENV_IS_IN_REMOTE) && \
|
||||
!defined(CONFIG_ENV_IS_IN_UBI) && \
|
||||
#if defined(CONFIG_ENV_IS_IN_EEPROM) || \
|
||||
defined(CONFIG_ENV_IS_IN_FLASH) || \
|
||||
defined(CONFIG_ENV_IS_IN_MMC) || \
|
||||
defined(CONFIG_ENV_IS_IN_FAT) || \
|
||||
defined(CONFIG_ENV_IS_IN_EXT4) || \
|
||||
defined(CONFIG_ENV_IS_IN_NAND) || \
|
||||
defined(CONFIG_ENV_IS_IN_NVRAM) || \
|
||||
defined(CONFIG_ENV_IS_IN_ONENAND) || \
|
||||
defined(CONFIG_ENV_IS_IN_SATA) || \
|
||||
defined(CONFIG_ENV_IS_IN_SPI_FLASH) || \
|
||||
defined(CONFIG_ENV_IS_IN_REMOTE) || \
|
||||
defined(CONFIG_ENV_IS_IN_UBI)
|
||||
|
||||
#define ENV_IS_IN_DEVICE
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(ENV_IS_IN_DEVICE) && \
|
||||
!defined(CONFIG_ENV_IS_NOWHERE)
|
||||
# error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|MMC|FAT|EXT4|\
|
||||
NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE
|
||||
@ -749,7 +755,7 @@ ulong env_get_ulong(const char *name, int base, ulong default_val)
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
|
||||
#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
|
||||
static int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
@ -1205,7 +1211,7 @@ static cmd_tbl_t cmd_env_sub[] = {
|
||||
#if defined(CONFIG_CMD_RUN)
|
||||
U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""),
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
|
||||
#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
|
||||
U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""),
|
||||
#endif
|
||||
U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 0, do_env_set, "", ""),
|
||||
@ -1280,7 +1286,7 @@ static char env_help_text[] =
|
||||
#if defined(CONFIG_CMD_RUN)
|
||||
"env run var [...] - run commands in an environment variable\n"
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
|
||||
#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
|
||||
"env save - save environment\n"
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_NVEDIT_EFI)
|
||||
|
@ -29,6 +29,8 @@ CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_SF=y
|
||||
CONFIG_CMD_SPI=y
|
||||
CONFIG_CMD_USB=y
|
||||
CONFIG_CMD_USB_MASS_STORAGE=y
|
||||
CONFIG_CMD_CACHE=y
|
||||
@ -37,8 +39,19 @@ CONFIG_CMD_TIMER=y
|
||||
CONFIG_CMD_PMIC=y
|
||||
CONFIG_CMD_REGULATOR=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_CMD_MTDPARTS=y
|
||||
CONFIG_CMD_UBI=y
|
||||
# CONFIG_SPL_DOS_PARTITION is not set
|
||||
CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
|
||||
CONFIG_ENV_IS_NOWHERE=y
|
||||
CONFIG_ENV_IS_IN_EXT4=y
|
||||
CONFIG_ENV_IS_IN_SPI_FLASH=y
|
||||
CONFIG_ENV_IS_IN_UBI=y
|
||||
CONFIG_ENV_EXT4_INTERFACE="mmc"
|
||||
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:auto"
|
||||
CONFIG_ENV_EXT4_FILE="/uboot.env"
|
||||
CONFIG_ENV_UBI_PART="UBI"
|
||||
CONFIG_ENV_UBI_VOLUME="uboot_config"
|
||||
CONFIG_STM32_ADC=y
|
||||
CONFIG_USB_FUNCTION_FASTBOOT=y
|
||||
CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
|
||||
@ -55,6 +68,20 @@ CONFIG_LED_GPIO=y
|
||||
CONFIG_DM_MMC=y
|
||||
CONFIG_SUPPORT_EMMC_BOOT=y
|
||||
CONFIG_STM32_SDMMC2=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_NAND=y
|
||||
CONFIG_NAND_STM32_FMC2=y
|
||||
CONFIG_DM_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH_BAR=y
|
||||
CONFIG_SPI_FLASH_MACRONIX=y
|
||||
CONFIG_SPI_FLASH_SPANSION=y
|
||||
CONFIG_SPI_FLASH_STMICRO=y
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
|
||||
CONFIG_SPI_FLASH_MTD=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_DWC_ETH_QOS=y
|
||||
CONFIG_PHY=y
|
||||
CONFIG_PHY_STM32_USBPHYC=y
|
||||
CONFIG_PINCONF=y
|
||||
@ -69,6 +96,10 @@ CONFIG_DM_REGULATOR_STM32_VREFBUF=y
|
||||
CONFIG_DM_REGULATOR_STPMIC1=y
|
||||
CONFIG_SERIAL_RX_BUFFER=y
|
||||
CONFIG_STM32_SERIAL=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_DM_SPI=y
|
||||
CONFIG_STM32_QSPI=y
|
||||
CONFIG_STM32_SPI=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_DM_USB=y
|
||||
CONFIG_DM_USB_GADGET=y
|
||||
@ -79,3 +110,5 @@ CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x0483
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0x5720
|
||||
CONFIG_USB_GADGET_DWC2_OTG=y
|
||||
CONFIG_WDT=y
|
||||
CONFIG_WDT_STM32MP=y
|
||||
|
@ -22,6 +22,8 @@ CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_SF=y
|
||||
CONFIG_CMD_SPI=y
|
||||
CONFIG_CMD_USB=y
|
||||
CONFIG_CMD_USB_MASS_STORAGE=y
|
||||
CONFIG_CMD_CACHE=y
|
||||
@ -30,7 +32,18 @@ CONFIG_CMD_TIMER=y
|
||||
CONFIG_CMD_PMIC=y
|
||||
CONFIG_CMD_REGULATOR=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_CMD_MTDPARTS=y
|
||||
CONFIG_CMD_UBI=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
|
||||
CONFIG_ENV_IS_NOWHERE=y
|
||||
CONFIG_ENV_IS_IN_EXT4=y
|
||||
CONFIG_ENV_IS_IN_SPI_FLASH=y
|
||||
CONFIG_ENV_IS_IN_UBI=y
|
||||
CONFIG_ENV_EXT4_INTERFACE="mmc"
|
||||
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:auto"
|
||||
CONFIG_ENV_EXT4_FILE="/uboot.env"
|
||||
CONFIG_ENV_UBI_PART="UBI"
|
||||
CONFIG_ENV_UBI_VOLUME="uboot_config"
|
||||
CONFIG_STM32_ADC=y
|
||||
CONFIG_USB_FUNCTION_FASTBOOT=y
|
||||
CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
|
||||
@ -47,6 +60,20 @@ CONFIG_LED_GPIO=y
|
||||
CONFIG_DM_MMC=y
|
||||
CONFIG_SUPPORT_EMMC_BOOT=y
|
||||
CONFIG_STM32_SDMMC2=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_NAND=y
|
||||
CONFIG_NAND_STM32_FMC2=y
|
||||
CONFIG_DM_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH_BAR=y
|
||||
CONFIG_SPI_FLASH_MACRONIX=y
|
||||
CONFIG_SPI_FLASH_SPANSION=y
|
||||
CONFIG_SPI_FLASH_STMICRO=y
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
|
||||
CONFIG_SPI_FLASH_MTD=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_ETH_DESIGNWARE=y
|
||||
CONFIG_PHY=y
|
||||
CONFIG_PHY_STM32_USBPHYC=y
|
||||
CONFIG_PINCONF=y
|
||||
@ -59,6 +86,10 @@ CONFIG_DM_REGULATOR_STM32_VREFBUF=y
|
||||
CONFIG_DM_REGULATOR_STPMIC1=y
|
||||
CONFIG_SERIAL_RX_BUFFER=y
|
||||
CONFIG_STM32_SERIAL=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_DM_SPI=y
|
||||
CONFIG_STM32_QSPI=y
|
||||
CONFIG_STM32_SPI=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_DM_USB=y
|
||||
CONFIG_DM_USB_GADGET=y
|
||||
@ -69,3 +100,5 @@ CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x0483
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0x5720
|
||||
CONFIG_USB_GADGET_DWC2_OTG=y
|
||||
CONFIG_WDT=y
|
||||
CONFIG_WDT_STM32MP=y
|
||||
|
@ -90,6 +90,7 @@
|
||||
#define RCC_PLL4CSGR 0x8A4
|
||||
#define RCC_I2C12CKSELR 0x8C0
|
||||
#define RCC_I2C35CKSELR 0x8C4
|
||||
#define RCC_SPI2S1CKSELR 0x8D8
|
||||
#define RCC_UART6CKSELR 0x8E4
|
||||
#define RCC_UART24CKSELR 0x8E8
|
||||
#define RCC_UART35CKSELR 0x8EC
|
||||
@ -298,6 +299,7 @@ enum stm32mp1_parent_sel {
|
||||
_STGEN_SEL,
|
||||
_DSI_SEL,
|
||||
_ADC12_SEL,
|
||||
_SPI1_SEL,
|
||||
_PARENT_SEL_NB,
|
||||
_UNKNOWN_SEL = 0xff,
|
||||
};
|
||||
@ -519,6 +521,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
|
||||
STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL),
|
||||
STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
|
||||
|
||||
STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 8, SPI1_K, _SPI1_SEL),
|
||||
STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
|
||||
|
||||
STM32MP1_CLK_SET_CLR_F(RCC_MP_APB3ENSETR, 13, VREF, _PCLK3),
|
||||
@ -555,7 +558,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
|
||||
|
||||
STM32MP1_CLK_SET_CLR(RCC_MP_AHB5ENSETR, 0, GPIOZ, _UNKNOWN_SEL),
|
||||
|
||||
STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 7, ETHCK, _ETH_SEL),
|
||||
STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 7, ETHCK_K, _ETH_SEL),
|
||||
STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 8, ETHTX, _UNKNOWN_SEL),
|
||||
STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 9, ETHRX, _UNKNOWN_SEL),
|
||||
STM32MP1_CLK_SET_CLR_F(RCC_MP_AHB6ENSETR, 10, ETHMAC, _ACLK),
|
||||
@ -589,6 +592,8 @@ static const u8 usbo_parents[] = {_PLL4_R, _USB_PHY_48};
|
||||
static const u8 stgen_parents[] = {_HSI_KER, _HSE_KER};
|
||||
static const u8 dsi_parents[] = {_DSI_PHY, _PLL4_P};
|
||||
static const u8 adc_parents[] = {_PLL4_R, _CK_PER, _PLL3_Q};
|
||||
static const u8 spi_parents[] = {_PLL4_P, _PLL3_Q, _I2S_CKIN, _CK_PER,
|
||||
_PLL3_R};
|
||||
|
||||
static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
|
||||
STM32MP1_CLK_PARENT(_I2C12_SEL, RCC_I2C12CKSELR, 0, 0x7, i2c12_parents),
|
||||
@ -613,6 +618,7 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
|
||||
STM32MP1_CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents),
|
||||
STM32MP1_CLK_PARENT(_DSI_SEL, RCC_DSICKSELR, 0, 0x1, dsi_parents),
|
||||
STM32MP1_CLK_PARENT(_ADC12_SEL, RCC_ADCCKSELR, 0, 0x1, adc_parents),
|
||||
STM32MP1_CLK_PARENT(_SPI1_SEL, RCC_SPI2S1CKSELR, 0, 0x7, spi_parents),
|
||||
};
|
||||
|
||||
#ifdef STM32MP1_CLOCK_TREE_INIT
|
||||
@ -727,6 +733,7 @@ char * const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] = {
|
||||
[_STGEN_SEL] = "STGEN",
|
||||
[_DSI_SEL] = "DSI",
|
||||
[_ADC12_SEL] = "ADC12",
|
||||
[_SPI1_SEL] = "SPI1",
|
||||
};
|
||||
|
||||
static const struct stm32mp1_clk_data stm32mp1_data = {
|
||||
|
@ -122,7 +122,6 @@ static const char *get_mtdparts(void)
|
||||
{
|
||||
__maybe_unused const char *mtdids = NULL;
|
||||
static char tmp_parts[MTDPARTS_MAXLEN];
|
||||
static bool use_defaults = true;
|
||||
const char *mtdparts = NULL;
|
||||
|
||||
if (gd->flags & GD_FLG_ENV_READY)
|
||||
@ -130,7 +129,7 @@ static const char *get_mtdparts(void)
|
||||
else if (env_get_f("mtdparts", tmp_parts, sizeof(tmp_parts)) != -1)
|
||||
mtdparts = tmp_parts;
|
||||
|
||||
if (mtdparts || !use_defaults)
|
||||
if (mtdparts)
|
||||
return mtdparts;
|
||||
|
||||
#if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
|
||||
@ -144,8 +143,6 @@ static const char *get_mtdparts(void)
|
||||
if (mtdparts)
|
||||
env_set("mtdparts", mtdparts);
|
||||
|
||||
use_defaults = false;
|
||||
|
||||
return mtdparts;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
* supports a single RGMII PHY. This configuration also has SW control over
|
||||
* all clock and reset signals to the HW block.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
@ -95,6 +94,7 @@ struct eqos_mac_regs {
|
||||
#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK 3
|
||||
#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED 0
|
||||
#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB 2
|
||||
#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV 1
|
||||
|
||||
#define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT 0
|
||||
#define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK 0xff
|
||||
@ -108,6 +108,7 @@ struct eqos_mac_regs {
|
||||
#define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT 16
|
||||
#define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT 8
|
||||
#define EQOS_MAC_MDIO_ADDRESS_CR_20_35 2
|
||||
#define EQOS_MAC_MDIO_ADDRESS_CR_250_300 5
|
||||
#define EQOS_MAC_MDIO_ADDRESS_SKAP BIT(4)
|
||||
#define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT 2
|
||||
#define EQOS_MAC_MDIO_ADDRESS_GOC_READ 3
|
||||
@ -260,6 +261,29 @@ struct eqos_desc {
|
||||
|
||||
struct eqos_config {
|
||||
bool reg_access_always_ok;
|
||||
int mdio_wait;
|
||||
int swr_wait;
|
||||
int config_mac;
|
||||
int config_mac_mdio;
|
||||
phy_interface_t (*interface)(struct udevice *dev);
|
||||
struct eqos_ops *ops;
|
||||
};
|
||||
|
||||
struct eqos_ops {
|
||||
void (*eqos_inval_desc)(void *desc);
|
||||
void (*eqos_flush_desc)(void *desc);
|
||||
void (*eqos_inval_buffer)(void *buf, size_t size);
|
||||
void (*eqos_flush_buffer)(void *buf, size_t size);
|
||||
int (*eqos_probe_resources)(struct udevice *dev);
|
||||
int (*eqos_remove_resources)(struct udevice *dev);
|
||||
int (*eqos_stop_resets)(struct udevice *dev);
|
||||
int (*eqos_start_resets)(struct udevice *dev);
|
||||
void (*eqos_stop_clks)(struct udevice *dev);
|
||||
int (*eqos_start_clks)(struct udevice *dev);
|
||||
int (*eqos_calibrate_pads)(struct udevice *dev);
|
||||
int (*eqos_disable_calibration)(struct udevice *dev);
|
||||
int (*eqos_set_tx_clk_speed)(struct udevice *dev);
|
||||
ulong (*eqos_get_tick_clk_rate)(struct udevice *dev);
|
||||
};
|
||||
|
||||
struct eqos_priv {
|
||||
@ -276,6 +300,7 @@ struct eqos_priv {
|
||||
struct clk clk_rx;
|
||||
struct clk clk_ptp_ref;
|
||||
struct clk clk_tx;
|
||||
struct clk clk_ck;
|
||||
struct clk clk_slave_bus;
|
||||
struct mii_dev *mii;
|
||||
struct phy_device *phy;
|
||||
@ -327,7 +352,7 @@ static void eqos_free_descs(void *descs)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void eqos_inval_desc(void *desc)
|
||||
static void eqos_inval_desc_tegra186(void *desc)
|
||||
{
|
||||
#ifndef CONFIG_SYS_NONCACHED_MEMORY
|
||||
unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
|
||||
@ -338,14 +363,36 @@ static void eqos_inval_desc(void *desc)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void eqos_flush_desc(void *desc)
|
||||
static void eqos_inval_desc_stm32(void *desc)
|
||||
{
|
||||
#ifndef CONFIG_SYS_NONCACHED_MEMORY
|
||||
unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
|
||||
unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
|
||||
ARCH_DMA_MINALIGN);
|
||||
|
||||
invalidate_dcache_range(start, end);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void eqos_flush_desc_tegra186(void *desc)
|
||||
{
|
||||
#ifndef CONFIG_SYS_NONCACHED_MEMORY
|
||||
flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void eqos_inval_buffer(void *buf, size_t size)
|
||||
static void eqos_flush_desc_stm32(void *desc)
|
||||
{
|
||||
#ifndef CONFIG_SYS_NONCACHED_MEMORY
|
||||
unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
|
||||
unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
|
||||
ARCH_DMA_MINALIGN);
|
||||
|
||||
flush_dcache_range(start, end);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void eqos_inval_buffer_tegra186(void *buf, size_t size)
|
||||
{
|
||||
unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1);
|
||||
unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN);
|
||||
@ -353,11 +400,29 @@ static void eqos_inval_buffer(void *buf, size_t size)
|
||||
invalidate_dcache_range(start, end);
|
||||
}
|
||||
|
||||
static void eqos_flush_buffer(void *buf, size_t size)
|
||||
static void eqos_inval_buffer_stm32(void *buf, size_t size)
|
||||
{
|
||||
unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
|
||||
unsigned long end = roundup((unsigned long)buf + size,
|
||||
ARCH_DMA_MINALIGN);
|
||||
|
||||
invalidate_dcache_range(start, end);
|
||||
}
|
||||
|
||||
static void eqos_flush_buffer_tegra186(void *buf, size_t size)
|
||||
{
|
||||
flush_cache((unsigned long)buf, size);
|
||||
}
|
||||
|
||||
static void eqos_flush_buffer_stm32(void *buf, size_t size)
|
||||
{
|
||||
unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
|
||||
unsigned long end = roundup((unsigned long)buf + size,
|
||||
ARCH_DMA_MINALIGN);
|
||||
|
||||
flush_dcache_range(start, end);
|
||||
}
|
||||
|
||||
static int eqos_mdio_wait_idle(struct eqos_priv *eqos)
|
||||
{
|
||||
return wait_for_bit_le32(&eqos->mac_regs->mdio_address,
|
||||
@ -386,14 +451,14 @@ static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
|
||||
EQOS_MAC_MDIO_ADDRESS_C45E;
|
||||
val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) |
|
||||
(mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
|
||||
(EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
|
||||
(eqos->config->config_mac_mdio <<
|
||||
EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) |
|
||||
(EQOS_MAC_MDIO_ADDRESS_GOC_READ <<
|
||||
EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) |
|
||||
EQOS_MAC_MDIO_ADDRESS_GB;
|
||||
writel(val, &eqos->mac_regs->mdio_address);
|
||||
|
||||
udelay(10);
|
||||
udelay(eqos->config->mdio_wait);
|
||||
|
||||
ret = eqos_mdio_wait_idle(eqos);
|
||||
if (ret) {
|
||||
@ -432,14 +497,14 @@ static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad,
|
||||
EQOS_MAC_MDIO_ADDRESS_C45E;
|
||||
val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) |
|
||||
(mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
|
||||
(EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
|
||||
(eqos->config->config_mac_mdio <<
|
||||
EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) |
|
||||
(EQOS_MAC_MDIO_ADDRESS_GOC_WRITE <<
|
||||
EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) |
|
||||
EQOS_MAC_MDIO_ADDRESS_GB;
|
||||
writel(val, &eqos->mac_regs->mdio_address);
|
||||
|
||||
udelay(10);
|
||||
udelay(eqos->config->mdio_wait);
|
||||
|
||||
ret = eqos_mdio_wait_idle(eqos);
|
||||
if (ret) {
|
||||
@ -509,6 +574,53 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int eqos_start_clks_stm32(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
debug("%s(dev=%p):\n", __func__, dev);
|
||||
|
||||
ret = clk_enable(&eqos->clk_master_bus);
|
||||
if (ret < 0) {
|
||||
pr_err("clk_enable(clk_master_bus) failed: %d", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = clk_enable(&eqos->clk_rx);
|
||||
if (ret < 0) {
|
||||
pr_err("clk_enable(clk_rx) failed: %d", ret);
|
||||
goto err_disable_clk_master_bus;
|
||||
}
|
||||
|
||||
ret = clk_enable(&eqos->clk_tx);
|
||||
if (ret < 0) {
|
||||
pr_err("clk_enable(clk_tx) failed: %d", ret);
|
||||
goto err_disable_clk_rx;
|
||||
}
|
||||
|
||||
if (clk_valid(&eqos->clk_ck)) {
|
||||
ret = clk_enable(&eqos->clk_ck);
|
||||
if (ret < 0) {
|
||||
pr_err("clk_enable(clk_ck) failed: %d", ret);
|
||||
goto err_disable_clk_tx;
|
||||
}
|
||||
}
|
||||
|
||||
debug("%s: OK\n", __func__);
|
||||
return 0;
|
||||
|
||||
err_disable_clk_tx:
|
||||
clk_disable(&eqos->clk_tx);
|
||||
err_disable_clk_rx:
|
||||
clk_disable(&eqos->clk_rx);
|
||||
err_disable_clk_master_bus:
|
||||
clk_disable(&eqos->clk_master_bus);
|
||||
err:
|
||||
debug("%s: FAILED: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void eqos_stop_clks_tegra186(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
@ -524,6 +636,21 @@ void eqos_stop_clks_tegra186(struct udevice *dev)
|
||||
debug("%s: OK\n", __func__);
|
||||
}
|
||||
|
||||
void eqos_stop_clks_stm32(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
|
||||
debug("%s(dev=%p):\n", __func__, dev);
|
||||
|
||||
clk_disable(&eqos->clk_tx);
|
||||
clk_disable(&eqos->clk_rx);
|
||||
clk_disable(&eqos->clk_master_bus);
|
||||
if (clk_valid(&eqos->clk_ck))
|
||||
clk_disable(&eqos->clk_ck);
|
||||
|
||||
debug("%s: OK\n", __func__);
|
||||
}
|
||||
|
||||
static int eqos_start_resets_tegra186(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
@ -563,6 +690,11 @@ static int eqos_start_resets_tegra186(struct udevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_start_resets_stm32(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_stop_resets_tegra186(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
@ -573,6 +705,11 @@ static int eqos_stop_resets_tegra186(struct udevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_stop_resets_stm32(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_calibrate_pads_tegra186(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
@ -632,6 +769,23 @@ static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev)
|
||||
return clk_get_rate(&eqos->clk_slave_bus);
|
||||
}
|
||||
|
||||
static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
|
||||
return clk_get_rate(&eqos->clk_master_bus);
|
||||
}
|
||||
|
||||
static int eqos_calibrate_pads_stm32(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_disable_calibration_stm32(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_set_full_duplex(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
@ -726,6 +880,11 @@ static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_set_tx_clk_speed_stm32(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_adjust_link(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
@ -766,23 +925,23 @@ static int eqos_adjust_link(struct udevice *dev)
|
||||
}
|
||||
|
||||
if (en_calibration) {
|
||||
ret = eqos_calibrate_pads_tegra186(dev);
|
||||
ret = eqos->config->ops->eqos_calibrate_pads(dev);
|
||||
if (ret < 0) {
|
||||
pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
|
||||
pr_err("eqos_calibrate_pads() failed: %d",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ret = eqos_disable_calibration_tegra186(dev);
|
||||
ret = eqos->config->ops->eqos_disable_calibration(dev);
|
||||
if (ret < 0) {
|
||||
pr_err("eqos_disable_calibration_tegra186() failed: %d",
|
||||
ret);
|
||||
pr_err("eqos_disable_calibration() failed: %d",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = eqos_set_tx_clk_speed_tegra186(dev);
|
||||
ret = eqos->config->ops->eqos_set_tx_clk_speed(dev);
|
||||
if (ret < 0) {
|
||||
pr_err("eqos_set_tx_clk_speed_tegra186() failed: %d", ret);
|
||||
pr_err("eqos_set_tx_clk_speed() failed: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -846,15 +1005,15 @@ static int eqos_start(struct udevice *dev)
|
||||
eqos->tx_desc_idx = 0;
|
||||
eqos->rx_desc_idx = 0;
|
||||
|
||||
ret = eqos_start_clks_tegra186(dev);
|
||||
ret = eqos->config->ops->eqos_start_clks(dev);
|
||||
if (ret < 0) {
|
||||
pr_err("eqos_start_clks_tegra186() failed: %d", ret);
|
||||
pr_err("eqos_start_clks() failed: %d", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = eqos_start_resets_tegra186(dev);
|
||||
ret = eqos->config->ops->eqos_start_resets(dev);
|
||||
if (ret < 0) {
|
||||
pr_err("eqos_start_resets_tegra186() failed: %d", ret);
|
||||
pr_err("eqos_start_resets() failed: %d", ret);
|
||||
goto err_stop_clks;
|
||||
}
|
||||
|
||||
@ -863,32 +1022,41 @@ static int eqos_start(struct udevice *dev)
|
||||
eqos->reg_access_ok = true;
|
||||
|
||||
ret = wait_for_bit_le32(&eqos->dma_regs->mode,
|
||||
EQOS_DMA_MODE_SWR, false, 10, false);
|
||||
EQOS_DMA_MODE_SWR, false,
|
||||
eqos->config->swr_wait, false);
|
||||
if (ret) {
|
||||
pr_err("EQOS_DMA_MODE_SWR stuck");
|
||||
goto err_stop_resets;
|
||||
}
|
||||
|
||||
ret = eqos_calibrate_pads_tegra186(dev);
|
||||
ret = eqos->config->ops->eqos_calibrate_pads(dev);
|
||||
if (ret < 0) {
|
||||
pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
|
||||
pr_err("eqos_calibrate_pads() failed: %d", ret);
|
||||
goto err_stop_resets;
|
||||
}
|
||||
rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
|
||||
|
||||
rate = eqos_get_tick_clk_rate_tegra186(dev);
|
||||
val = (rate / 1000000) - 1;
|
||||
writel(val, &eqos->mac_regs->us_tic_counter);
|
||||
|
||||
eqos->phy = phy_connect(eqos->mii, 0, dev, 0);
|
||||
/*
|
||||
* if PHY was already connected and configured,
|
||||
* don't need to reconnect/reconfigure again
|
||||
*/
|
||||
if (!eqos->phy) {
|
||||
pr_err("phy_connect() failed");
|
||||
goto err_stop_resets;
|
||||
}
|
||||
ret = phy_config(eqos->phy);
|
||||
if (ret < 0) {
|
||||
pr_err("phy_config() failed: %d", ret);
|
||||
goto err_shutdown_phy;
|
||||
eqos->phy = phy_connect(eqos->mii, 0, dev,
|
||||
eqos->config->interface(dev));
|
||||
if (!eqos->phy) {
|
||||
pr_err("phy_connect() failed");
|
||||
goto err_stop_resets;
|
||||
}
|
||||
ret = phy_config(eqos->phy);
|
||||
if (ret < 0) {
|
||||
pr_err("phy_config() failed: %d", ret);
|
||||
goto err_shutdown_phy;
|
||||
}
|
||||
}
|
||||
|
||||
ret = phy_startup(eqos->phy);
|
||||
if (ret < 0) {
|
||||
pr_err("phy_startup() failed: %d", ret);
|
||||
@ -993,7 +1161,7 @@ static int eqos_start(struct udevice *dev)
|
||||
clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0,
|
||||
EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK <<
|
||||
EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT,
|
||||
EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB <<
|
||||
eqos->config->config_mac <<
|
||||
EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT);
|
||||
|
||||
/* Set TX flow control parameters */
|
||||
@ -1074,7 +1242,7 @@ static int eqos_start(struct udevice *dev)
|
||||
(i * EQOS_MAX_PACKET_SIZE));
|
||||
rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
|
||||
}
|
||||
flush_cache((unsigned long)eqos->descs, EQOS_DESCRIPTORS_SIZE);
|
||||
eqos->config->ops->eqos_flush_desc(eqos->descs);
|
||||
|
||||
writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress);
|
||||
writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address);
|
||||
@ -1113,11 +1281,10 @@ static int eqos_start(struct udevice *dev)
|
||||
|
||||
err_shutdown_phy:
|
||||
phy_shutdown(eqos->phy);
|
||||
eqos->phy = NULL;
|
||||
err_stop_resets:
|
||||
eqos_stop_resets_tegra186(dev);
|
||||
eqos->config->ops->eqos_stop_resets(dev);
|
||||
err_stop_clks:
|
||||
eqos_stop_clks_tegra186(dev);
|
||||
eqos->config->ops->eqos_stop_clks(dev);
|
||||
err:
|
||||
pr_err("FAILED: %d", ret);
|
||||
return ret;
|
||||
@ -1170,10 +1337,9 @@ void eqos_stop(struct udevice *dev)
|
||||
|
||||
if (eqos->phy) {
|
||||
phy_shutdown(eqos->phy);
|
||||
eqos->phy = NULL;
|
||||
}
|
||||
eqos_stop_resets_tegra186(dev);
|
||||
eqos_stop_clks_tegra186(dev);
|
||||
eqos->config->ops->eqos_stop_resets(dev);
|
||||
eqos->config->ops->eqos_stop_clks(dev);
|
||||
|
||||
debug("%s: OK\n", __func__);
|
||||
}
|
||||
@ -1188,7 +1354,7 @@ int eqos_send(struct udevice *dev, void *packet, int length)
|
||||
length);
|
||||
|
||||
memcpy(eqos->tx_dma_buf, packet, length);
|
||||
eqos_flush_buffer(eqos->tx_dma_buf, length);
|
||||
eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length);
|
||||
|
||||
tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]);
|
||||
eqos->tx_desc_idx++;
|
||||
@ -1203,12 +1369,12 @@ int eqos_send(struct udevice *dev, void *packet, int length)
|
||||
*/
|
||||
mb();
|
||||
tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length;
|
||||
eqos_flush_desc(tx_desc);
|
||||
eqos->config->ops->eqos_flush_desc(tx_desc);
|
||||
|
||||
writel((ulong)(tx_desc + 1), &eqos->dma_regs->ch0_txdesc_tail_pointer);
|
||||
|
||||
for (i = 0; i < 1000000; i++) {
|
||||
eqos_inval_desc(tx_desc);
|
||||
eqos->config->ops->eqos_inval_desc(tx_desc);
|
||||
if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN))
|
||||
return 0;
|
||||
udelay(1);
|
||||
@ -1238,7 +1404,7 @@ int eqos_recv(struct udevice *dev, int flags, uchar **packetp)
|
||||
length = rx_desc->des3 & 0x7fff;
|
||||
debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length);
|
||||
|
||||
eqos_inval_buffer(*packetp, length);
|
||||
eqos->config->ops->eqos_inval_buffer(*packetp, length);
|
||||
|
||||
return length;
|
||||
}
|
||||
@ -1269,7 +1435,7 @@ int eqos_free_pkt(struct udevice *dev, uchar *packet, int length)
|
||||
*/
|
||||
mb();
|
||||
rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
|
||||
eqos_flush_desc(rx_desc);
|
||||
eqos->config->ops->eqos_flush_desc(rx_desc);
|
||||
|
||||
writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
|
||||
|
||||
@ -1304,7 +1470,7 @@ static int eqos_probe_resources_core(struct udevice *dev)
|
||||
ret = -ENOMEM;
|
||||
goto err_free_descs;
|
||||
}
|
||||
debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
|
||||
debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf);
|
||||
|
||||
eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE);
|
||||
if (!eqos->rx_dma_buf) {
|
||||
@ -1312,7 +1478,7 @@ static int eqos_probe_resources_core(struct udevice *dev)
|
||||
ret = -ENOMEM;
|
||||
goto err_free_tx_dma_buf;
|
||||
}
|
||||
debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf);
|
||||
debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
|
||||
|
||||
eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE);
|
||||
if (!eqos->rx_pkt) {
|
||||
@ -1424,6 +1590,98 @@ err_free_reset_eqos:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* board-specific Ethernet Interface initializations. */
|
||||
__weak int board_interface_eth_init(int interface_type, bool eth_clk_sel_reg,
|
||||
bool eth_ref_clk_sel_reg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_probe_resources_stm32(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
int ret;
|
||||
phy_interface_t interface;
|
||||
bool eth_clk_sel_reg = false;
|
||||
bool eth_ref_clk_sel_reg = false;
|
||||
|
||||
debug("%s(dev=%p):\n", __func__, dev);
|
||||
|
||||
interface = eqos->config->interface(dev);
|
||||
|
||||
if (interface == PHY_INTERFACE_MODE_NONE) {
|
||||
pr_err("Invalid PHY interface\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Gigabit Ethernet 125MHz clock selection. */
|
||||
eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
|
||||
|
||||
/* Ethernet 50Mhz RMII clock selection */
|
||||
eth_ref_clk_sel_reg =
|
||||
dev_read_bool(dev, "st,eth_ref_clk_sel");
|
||||
|
||||
ret = board_interface_eth_init(interface, eth_clk_sel_reg,
|
||||
eth_ref_clk_sel_reg);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
|
||||
if (ret) {
|
||||
pr_err("clk_get_by_name(master_bus) failed: %d", ret);
|
||||
goto err_probe;
|
||||
}
|
||||
|
||||
ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx);
|
||||
if (ret) {
|
||||
pr_err("clk_get_by_name(rx) failed: %d", ret);
|
||||
goto err_free_clk_master_bus;
|
||||
}
|
||||
|
||||
ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx);
|
||||
if (ret) {
|
||||
pr_err("clk_get_by_name(tx) failed: %d", ret);
|
||||
goto err_free_clk_rx;
|
||||
}
|
||||
|
||||
/* Get ETH_CLK clocks (optional) */
|
||||
ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck);
|
||||
if (ret)
|
||||
pr_warn("No phy clock provided %d", ret);
|
||||
|
||||
debug("%s: OK\n", __func__);
|
||||
return 0;
|
||||
|
||||
err_free_clk_rx:
|
||||
clk_free(&eqos->clk_rx);
|
||||
err_free_clk_master_bus:
|
||||
clk_free(&eqos->clk_master_bus);
|
||||
err_probe:
|
||||
|
||||
debug("%s: returns %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static phy_interface_t eqos_get_interface_stm32(struct udevice *dev)
|
||||
{
|
||||
const char *phy_mode;
|
||||
phy_interface_t interface = PHY_INTERFACE_MODE_NONE;
|
||||
|
||||
debug("%s(dev=%p):\n", __func__, dev);
|
||||
|
||||
phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
|
||||
NULL);
|
||||
if (phy_mode)
|
||||
interface = phy_get_interface_by_name(phy_mode);
|
||||
|
||||
return interface;
|
||||
}
|
||||
|
||||
static phy_interface_t eqos_get_interface_tegra186(struct udevice *dev)
|
||||
{
|
||||
return PHY_INTERFACE_MODE_MII;
|
||||
}
|
||||
|
||||
static int eqos_remove_resources_tegra186(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
@ -1442,6 +1700,22 @@ static int eqos_remove_resources_tegra186(struct udevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_remove_resources_stm32(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
|
||||
debug("%s(dev=%p):\n", __func__, dev);
|
||||
|
||||
clk_free(&eqos->clk_tx);
|
||||
clk_free(&eqos->clk_rx);
|
||||
clk_free(&eqos->clk_master_bus);
|
||||
if (clk_valid(&eqos->clk_ck))
|
||||
clk_free(&eqos->clk_ck);
|
||||
|
||||
debug("%s: OK\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_probe(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
@ -1468,15 +1742,16 @@ static int eqos_probe(struct udevice *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = eqos_probe_resources_tegra186(dev);
|
||||
ret = eqos->config->ops->eqos_probe_resources(dev);
|
||||
if (ret < 0) {
|
||||
pr_err("eqos_probe_resources_tegra186() failed: %d", ret);
|
||||
pr_err("eqos_probe_resources() failed: %d", ret);
|
||||
goto err_remove_resources_core;
|
||||
}
|
||||
|
||||
eqos->mii = mdio_alloc();
|
||||
if (!eqos->mii) {
|
||||
pr_err("mdio_alloc() failed");
|
||||
ret = -ENOMEM;
|
||||
goto err_remove_resources_tegra;
|
||||
}
|
||||
eqos->mii->read = eqos_mdio_read;
|
||||
@ -1496,7 +1771,7 @@ static int eqos_probe(struct udevice *dev)
|
||||
err_free_mdio:
|
||||
mdio_free(eqos->mii);
|
||||
err_remove_resources_tegra:
|
||||
eqos_remove_resources_tegra186(dev);
|
||||
eqos->config->ops->eqos_remove_resources(dev);
|
||||
err_remove_resources_core:
|
||||
eqos_remove_resources_core(dev);
|
||||
|
||||
@ -1512,7 +1787,8 @@ static int eqos_remove(struct udevice *dev)
|
||||
|
||||
mdio_unregister(eqos->mii);
|
||||
mdio_free(eqos->mii);
|
||||
eqos_remove_resources_tegra186(dev);
|
||||
eqos->config->ops->eqos_remove_resources(dev);
|
||||
|
||||
eqos_probe_resources_core(dev);
|
||||
|
||||
debug("%s: OK\n", __func__);
|
||||
@ -1528,8 +1804,58 @@ static const struct eth_ops eqos_ops = {
|
||||
.write_hwaddr = eqos_write_hwaddr,
|
||||
};
|
||||
|
||||
static struct eqos_ops eqos_tegra186_ops = {
|
||||
.eqos_inval_desc = eqos_inval_desc_tegra186,
|
||||
.eqos_flush_desc = eqos_flush_desc_tegra186,
|
||||
.eqos_inval_buffer = eqos_inval_buffer_tegra186,
|
||||
.eqos_flush_buffer = eqos_flush_buffer_tegra186,
|
||||
.eqos_probe_resources = eqos_probe_resources_tegra186,
|
||||
.eqos_remove_resources = eqos_remove_resources_tegra186,
|
||||
.eqos_stop_resets = eqos_stop_resets_tegra186,
|
||||
.eqos_start_resets = eqos_start_resets_tegra186,
|
||||
.eqos_stop_clks = eqos_stop_clks_tegra186,
|
||||
.eqos_start_clks = eqos_start_clks_tegra186,
|
||||
.eqos_calibrate_pads = eqos_calibrate_pads_tegra186,
|
||||
.eqos_disable_calibration = eqos_disable_calibration_tegra186,
|
||||
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186,
|
||||
.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186
|
||||
};
|
||||
|
||||
static const struct eqos_config eqos_tegra186_config = {
|
||||
.reg_access_always_ok = false,
|
||||
.mdio_wait = 10,
|
||||
.swr_wait = 10,
|
||||
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
|
||||
.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35,
|
||||
.interface = eqos_get_interface_tegra186,
|
||||
.ops = &eqos_tegra186_ops
|
||||
};
|
||||
|
||||
static struct eqos_ops eqos_stm32_ops = {
|
||||
.eqos_inval_desc = eqos_inval_desc_stm32,
|
||||
.eqos_flush_desc = eqos_flush_desc_stm32,
|
||||
.eqos_inval_buffer = eqos_inval_buffer_stm32,
|
||||
.eqos_flush_buffer = eqos_flush_buffer_stm32,
|
||||
.eqos_probe_resources = eqos_probe_resources_stm32,
|
||||
.eqos_remove_resources = eqos_remove_resources_stm32,
|
||||
.eqos_stop_resets = eqos_stop_resets_stm32,
|
||||
.eqos_start_resets = eqos_start_resets_stm32,
|
||||
.eqos_stop_clks = eqos_stop_clks_stm32,
|
||||
.eqos_start_clks = eqos_start_clks_stm32,
|
||||
.eqos_calibrate_pads = eqos_calibrate_pads_stm32,
|
||||
.eqos_disable_calibration = eqos_disable_calibration_stm32,
|
||||
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32,
|
||||
.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32
|
||||
};
|
||||
|
||||
static const struct eqos_config eqos_stm32_config = {
|
||||
.reg_access_always_ok = false,
|
||||
.mdio_wait = 10000,
|
||||
.swr_wait = 50,
|
||||
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
|
||||
.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
|
||||
.interface = eqos_get_interface_stm32,
|
||||
.ops = &eqos_stm32_ops
|
||||
};
|
||||
|
||||
static const struct udevice_id eqos_ids[] = {
|
||||
@ -1537,6 +1863,11 @@ static const struct udevice_id eqos_ids[] = {
|
||||
.compatible = "nvidia,tegra186-eqos",
|
||||
.data = (ulong)&eqos_tegra186_config
|
||||
},
|
||||
{
|
||||
.compatible = "snps,dwmac-4.20a",
|
||||
.data = (ulong)&eqos_stm32_config
|
||||
},
|
||||
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -239,6 +239,14 @@ config STM32_QSPI
|
||||
used to access the SPI NOR flash chips on platforms embedding
|
||||
this ST IP core.
|
||||
|
||||
config STM32_SPI
|
||||
bool "STM32 SPI driver"
|
||||
depends on ARCH_STM32MP
|
||||
help
|
||||
Enable the STM32 Serial Peripheral Interface (SPI) driver for STM32MP
|
||||
SoCs. This uses driver model and requires a device tree binding to
|
||||
operate.
|
||||
|
||||
config TEGRA114_SPI
|
||||
bool "nVidia Tegra114 SPI driver"
|
||||
help
|
||||
|
@ -53,6 +53,7 @@ obj-$(CONFIG_SPI_SUNXI) += spi-sunxi.o
|
||||
obj-$(CONFIG_SH_SPI) += sh_spi.o
|
||||
obj-$(CONFIG_SH_QSPI) += sh_qspi.o
|
||||
obj-$(CONFIG_STM32_QSPI) += stm32_qspi.o
|
||||
obj-$(CONFIG_STM32_SPI) += stm32_spi.o
|
||||
obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
|
||||
obj-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
|
||||
obj-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
|
||||
|
615
drivers/spi/stm32_spi.c
Normal file
615
drivers/spi/stm32_spi.c
Normal file
@ -0,0 +1,615 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2019, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* Driver for STMicroelectronics Serial peripheral interface (SPI)
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <reset.h>
|
||||
#include <spi.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
/* STM32 SPI registers */
|
||||
#define STM32_SPI_CR1 0x00
|
||||
#define STM32_SPI_CR2 0x04
|
||||
#define STM32_SPI_CFG1 0x08
|
||||
#define STM32_SPI_CFG2 0x0C
|
||||
#define STM32_SPI_SR 0x14
|
||||
#define STM32_SPI_IFCR 0x18
|
||||
#define STM32_SPI_TXDR 0x20
|
||||
#define STM32_SPI_RXDR 0x30
|
||||
#define STM32_SPI_I2SCFGR 0x50
|
||||
|
||||
/* STM32_SPI_CR1 bit fields */
|
||||
#define SPI_CR1_SPE BIT(0)
|
||||
#define SPI_CR1_MASRX BIT(8)
|
||||
#define SPI_CR1_CSTART BIT(9)
|
||||
#define SPI_CR1_CSUSP BIT(10)
|
||||
#define SPI_CR1_HDDIR BIT(11)
|
||||
#define SPI_CR1_SSI BIT(12)
|
||||
|
||||
/* STM32_SPI_CR2 bit fields */
|
||||
#define SPI_CR2_TSIZE GENMASK(15, 0)
|
||||
|
||||
/* STM32_SPI_CFG1 bit fields */
|
||||
#define SPI_CFG1_DSIZE GENMASK(4, 0)
|
||||
#define SPI_CFG1_DSIZE_MIN 3
|
||||
#define SPI_CFG1_FTHLV_SHIFT 5
|
||||
#define SPI_CFG1_FTHLV GENMASK(8, 5)
|
||||
#define SPI_CFG1_MBR_SHIFT 28
|
||||
#define SPI_CFG1_MBR GENMASK(30, 28)
|
||||
#define SPI_CFG1_MBR_MIN 0
|
||||
#define SPI_CFG1_MBR_MAX FIELD_GET(SPI_CFG1_MBR, SPI_CFG1_MBR)
|
||||
|
||||
/* STM32_SPI_CFG2 bit fields */
|
||||
#define SPI_CFG2_COMM_SHIFT 17
|
||||
#define SPI_CFG2_COMM GENMASK(18, 17)
|
||||
#define SPI_CFG2_MASTER BIT(22)
|
||||
#define SPI_CFG2_LSBFRST BIT(23)
|
||||
#define SPI_CFG2_CPHA BIT(24)
|
||||
#define SPI_CFG2_CPOL BIT(25)
|
||||
#define SPI_CFG2_SSM BIT(26)
|
||||
#define SPI_CFG2_AFCNTR BIT(31)
|
||||
|
||||
/* STM32_SPI_SR bit fields */
|
||||
#define SPI_SR_RXP BIT(0)
|
||||
#define SPI_SR_TXP BIT(1)
|
||||
#define SPI_SR_EOT BIT(3)
|
||||
#define SPI_SR_TXTF BIT(4)
|
||||
#define SPI_SR_OVR BIT(6)
|
||||
#define SPI_SR_SUSP BIT(11)
|
||||
#define SPI_SR_RXPLVL_SHIFT 13
|
||||
#define SPI_SR_RXPLVL GENMASK(14, 13)
|
||||
#define SPI_SR_RXWNE BIT(15)
|
||||
|
||||
/* STM32_SPI_IFCR bit fields */
|
||||
#define SPI_IFCR_ALL GENMASK(11, 3)
|
||||
|
||||
/* STM32_SPI_I2SCFGR bit fields */
|
||||
#define SPI_I2SCFGR_I2SMOD BIT(0)
|
||||
|
||||
#define MAX_CS_COUNT 4
|
||||
|
||||
/* SPI Master Baud Rate min/max divisor */
|
||||
#define STM32_MBR_DIV_MIN (2 << SPI_CFG1_MBR_MIN)
|
||||
#define STM32_MBR_DIV_MAX (2 << SPI_CFG1_MBR_MAX)
|
||||
|
||||
#define STM32_SPI_TIMEOUT_US 100000
|
||||
|
||||
/* SPI Communication mode */
|
||||
#define SPI_FULL_DUPLEX 0
|
||||
#define SPI_SIMPLEX_TX 1
|
||||
#define SPI_SIMPLEX_RX 2
|
||||
#define SPI_HALF_DUPLEX 3
|
||||
|
||||
struct stm32_spi_priv {
|
||||
void __iomem *base;
|
||||
struct clk clk;
|
||||
struct reset_ctl rst_ctl;
|
||||
struct gpio_desc cs_gpios[MAX_CS_COUNT];
|
||||
ulong bus_clk_rate;
|
||||
unsigned int fifo_size;
|
||||
unsigned int cur_bpw;
|
||||
unsigned int cur_hz;
|
||||
unsigned int cur_xferlen; /* current transfer length in bytes */
|
||||
int tx_len; /* number of data to be written in bytes */
|
||||
int rx_len; /* number of data to be read in bytes */
|
||||
const void *tx_buf; /* data to be written, or NULL */
|
||||
void *rx_buf; /* data to be read, or NULL */
|
||||
u32 cur_mode;
|
||||
bool cs_high;
|
||||
};
|
||||
|
||||
static void stm32_spi_write_txfifo(struct stm32_spi_priv *priv)
|
||||
{
|
||||
while ((priv->tx_len > 0) &&
|
||||
(readl(priv->base + STM32_SPI_SR) & SPI_SR_TXP)) {
|
||||
u32 offs = priv->cur_xferlen - priv->tx_len;
|
||||
|
||||
if (priv->tx_len >= sizeof(u32) &&
|
||||
IS_ALIGNED((uintptr_t)(priv->tx_buf + offs), sizeof(u32))) {
|
||||
const u32 *tx_buf32 = (const u32 *)(priv->tx_buf + offs);
|
||||
|
||||
writel(*tx_buf32, priv->base + STM32_SPI_TXDR);
|
||||
priv->tx_len -= sizeof(u32);
|
||||
} else if (priv->tx_len >= sizeof(u16) &&
|
||||
IS_ALIGNED((uintptr_t)(priv->tx_buf + offs), sizeof(u16))) {
|
||||
const u16 *tx_buf16 = (const u16 *)(priv->tx_buf + offs);
|
||||
|
||||
writew(*tx_buf16, priv->base + STM32_SPI_TXDR);
|
||||
priv->tx_len -= sizeof(u16);
|
||||
} else {
|
||||
const u8 *tx_buf8 = (const u8 *)(priv->tx_buf + offs);
|
||||
|
||||
writeb(*tx_buf8, priv->base + STM32_SPI_TXDR);
|
||||
priv->tx_len -= sizeof(u8);
|
||||
}
|
||||
}
|
||||
|
||||
debug("%s: %d bytes left\n", __func__, priv->tx_len);
|
||||
}
|
||||
|
||||
static void stm32_spi_read_rxfifo(struct stm32_spi_priv *priv)
|
||||
{
|
||||
u32 sr = readl(priv->base + STM32_SPI_SR);
|
||||
u32 rxplvl = (sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_SHIFT;
|
||||
|
||||
while ((priv->rx_len > 0) &&
|
||||
((sr & SPI_SR_RXP) ||
|
||||
((sr & SPI_SR_EOT) && ((sr & SPI_SR_RXWNE) || (rxplvl > 0))))) {
|
||||
u32 offs = priv->cur_xferlen - priv->rx_len;
|
||||
|
||||
if (IS_ALIGNED((uintptr_t)(priv->rx_buf + offs), sizeof(u32)) &&
|
||||
(priv->rx_len >= sizeof(u32) || (sr & SPI_SR_RXWNE))) {
|
||||
u32 *rx_buf32 = (u32 *)(priv->rx_buf + offs);
|
||||
|
||||
*rx_buf32 = readl(priv->base + STM32_SPI_RXDR);
|
||||
priv->rx_len -= sizeof(u32);
|
||||
} else if (IS_ALIGNED((uintptr_t)(priv->rx_buf + offs), sizeof(u16)) &&
|
||||
(priv->rx_len >= sizeof(u16) ||
|
||||
(!(sr & SPI_SR_RXWNE) &&
|
||||
(rxplvl >= 2 || priv->cur_bpw > 8)))) {
|
||||
u16 *rx_buf16 = (u16 *)(priv->rx_buf + offs);
|
||||
|
||||
*rx_buf16 = readw(priv->base + STM32_SPI_RXDR);
|
||||
priv->rx_len -= sizeof(u16);
|
||||
} else {
|
||||
u8 *rx_buf8 = (u8 *)(priv->rx_buf + offs);
|
||||
|
||||
*rx_buf8 = readb(priv->base + STM32_SPI_RXDR);
|
||||
priv->rx_len -= sizeof(u8);
|
||||
}
|
||||
|
||||
sr = readl(priv->base + STM32_SPI_SR);
|
||||
rxplvl = (sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_SHIFT;
|
||||
}
|
||||
|
||||
debug("%s: %d bytes left\n", __func__, priv->rx_len);
|
||||
}
|
||||
|
||||
static int stm32_spi_enable(struct stm32_spi_priv *priv)
|
||||
{
|
||||
debug("%s\n", __func__);
|
||||
|
||||
/* Enable the SPI hardware */
|
||||
setbits_le32(priv->base + STM32_SPI_CR1, SPI_CR1_SPE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_spi_disable(struct stm32_spi_priv *priv)
|
||||
{
|
||||
debug("%s\n", __func__);
|
||||
|
||||
/* Disable the SPI hardware */
|
||||
clrbits_le32(priv->base + STM32_SPI_CR1, SPI_CR1_SPE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_spi_claim_bus(struct udevice *slave)
|
||||
{
|
||||
struct udevice *bus = dev_get_parent(slave);
|
||||
struct stm32_spi_priv *priv = dev_get_priv(bus);
|
||||
|
||||
debug("%s\n", __func__);
|
||||
|
||||
/* Enable the SPI hardware */
|
||||
return stm32_spi_enable(priv);
|
||||
}
|
||||
|
||||
static int stm32_spi_release_bus(struct udevice *slave)
|
||||
{
|
||||
struct udevice *bus = dev_get_parent(slave);
|
||||
struct stm32_spi_priv *priv = dev_get_priv(bus);
|
||||
|
||||
debug("%s\n", __func__);
|
||||
|
||||
/* Disable the SPI hardware */
|
||||
return stm32_spi_disable(priv);
|
||||
}
|
||||
|
||||
static void stm32_spi_stopxfer(struct udevice *dev)
|
||||
{
|
||||
struct stm32_spi_priv *priv = dev_get_priv(dev);
|
||||
u32 cr1, sr;
|
||||
int ret;
|
||||
|
||||
debug("%s\n", __func__);
|
||||
|
||||
cr1 = readl(priv->base + STM32_SPI_CR1);
|
||||
|
||||
if (!(cr1 & SPI_CR1_SPE))
|
||||
return;
|
||||
|
||||
/* Wait on EOT or suspend the flow */
|
||||
ret = readl_poll_timeout(priv->base + STM32_SPI_SR, sr,
|
||||
!(sr & SPI_SR_EOT), 100000);
|
||||
if (ret < 0) {
|
||||
if (cr1 & SPI_CR1_CSTART) {
|
||||
writel(cr1 | SPI_CR1_CSUSP, priv->base + STM32_SPI_CR1);
|
||||
if (readl_poll_timeout(priv->base + STM32_SPI_SR,
|
||||
sr, !(sr & SPI_SR_SUSP),
|
||||
100000) < 0)
|
||||
dev_err(dev, "Suspend request timeout\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* clear status flags */
|
||||
setbits_le32(priv->base + STM32_SPI_IFCR, SPI_IFCR_ALL);
|
||||
}
|
||||
|
||||
static int stm32_spi_set_cs(struct udevice *dev, unsigned int cs, bool enable)
|
||||
{
|
||||
struct stm32_spi_priv *priv = dev_get_priv(dev);
|
||||
|
||||
debug("%s: cs=%d enable=%d\n", __func__, cs, enable);
|
||||
|
||||
if (cs >= MAX_CS_COUNT)
|
||||
return -ENODEV;
|
||||
|
||||
if (!dm_gpio_is_valid(&priv->cs_gpios[cs]))
|
||||
return -EINVAL;
|
||||
|
||||
if (priv->cs_high)
|
||||
enable = !enable;
|
||||
|
||||
return dm_gpio_set_value(&priv->cs_gpios[cs], enable ? 1 : 0);
|
||||
}
|
||||
|
||||
static int stm32_spi_set_mode(struct udevice *bus, uint mode)
|
||||
{
|
||||
struct stm32_spi_priv *priv = dev_get_priv(bus);
|
||||
u32 cfg2_clrb = 0, cfg2_setb = 0;
|
||||
|
||||
debug("%s: mode=%d\n", __func__, mode);
|
||||
|
||||
if (mode & SPI_CPOL)
|
||||
cfg2_setb |= SPI_CFG2_CPOL;
|
||||
else
|
||||
cfg2_clrb |= SPI_CFG2_CPOL;
|
||||
|
||||
if (mode & SPI_CPHA)
|
||||
cfg2_setb |= SPI_CFG2_CPHA;
|
||||
else
|
||||
cfg2_clrb |= SPI_CFG2_CPHA;
|
||||
|
||||
if (mode & SPI_LSB_FIRST)
|
||||
cfg2_setb |= SPI_CFG2_LSBFRST;
|
||||
else
|
||||
cfg2_clrb |= SPI_CFG2_LSBFRST;
|
||||
|
||||
if (cfg2_clrb || cfg2_setb)
|
||||
clrsetbits_le32(priv->base + STM32_SPI_CFG2,
|
||||
cfg2_clrb, cfg2_setb);
|
||||
|
||||
if (mode & SPI_CS_HIGH)
|
||||
priv->cs_high = true;
|
||||
else
|
||||
priv->cs_high = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_spi_set_fthlv(struct udevice *dev, u32 xfer_len)
|
||||
{
|
||||
struct stm32_spi_priv *priv = dev_get_priv(dev);
|
||||
u32 fthlv, half_fifo;
|
||||
|
||||
/* data packet should not exceed 1/2 of fifo space */
|
||||
half_fifo = (priv->fifo_size / 2);
|
||||
|
||||
/* data_packet should not exceed transfer length */
|
||||
fthlv = (half_fifo > xfer_len) ? xfer_len : half_fifo;
|
||||
|
||||
/* align packet size with data registers access */
|
||||
fthlv -= (fthlv % 4);
|
||||
|
||||
if (!fthlv)
|
||||
fthlv = 1;
|
||||
clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_FTHLV,
|
||||
(fthlv - 1) << SPI_CFG1_FTHLV_SHIFT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_spi_set_speed(struct udevice *bus, uint hz)
|
||||
{
|
||||
struct stm32_spi_priv *priv = dev_get_priv(bus);
|
||||
u32 div, mbrdiv;
|
||||
|
||||
debug("%s: hz=%d\n", __func__, hz);
|
||||
|
||||
if (priv->cur_hz == hz)
|
||||
return 0;
|
||||
|
||||
div = DIV_ROUND_UP(priv->bus_clk_rate, hz);
|
||||
|
||||
if (div < STM32_MBR_DIV_MIN ||
|
||||
div > STM32_MBR_DIV_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
/* Determine the first power of 2 greater than or equal to div */
|
||||
if (div & (div - 1))
|
||||
mbrdiv = fls(div);
|
||||
else
|
||||
mbrdiv = fls(div) - 1;
|
||||
|
||||
if ((mbrdiv - 1) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_MBR,
|
||||
(mbrdiv - 1) << SPI_CFG1_MBR_SHIFT);
|
||||
|
||||
priv->cur_hz = hz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_spi_xfer(struct udevice *slave, unsigned int bitlen,
|
||||
const void *dout, void *din, unsigned long flags)
|
||||
{
|
||||
struct udevice *bus = dev_get_parent(slave);
|
||||
struct dm_spi_slave_platdata *slave_plat;
|
||||
struct stm32_spi_priv *priv = dev_get_priv(bus);
|
||||
u32 sr;
|
||||
u32 ifcr = 0;
|
||||
u32 xferlen;
|
||||
u32 mode;
|
||||
int xfer_status = 0;
|
||||
|
||||
xferlen = bitlen / 8;
|
||||
|
||||
if (xferlen <= SPI_CR2_TSIZE)
|
||||
writel(xferlen, priv->base + STM32_SPI_CR2);
|
||||
else
|
||||
return -EMSGSIZE;
|
||||
|
||||
priv->tx_buf = dout;
|
||||
priv->rx_buf = din;
|
||||
priv->tx_len = priv->tx_buf ? bitlen / 8 : 0;
|
||||
priv->rx_len = priv->rx_buf ? bitlen / 8 : 0;
|
||||
|
||||
mode = SPI_FULL_DUPLEX;
|
||||
if (!priv->tx_buf)
|
||||
mode = SPI_SIMPLEX_RX;
|
||||
else if (!priv->rx_buf)
|
||||
mode = SPI_SIMPLEX_TX;
|
||||
|
||||
if (priv->cur_xferlen != xferlen || priv->cur_mode != mode) {
|
||||
priv->cur_mode = mode;
|
||||
priv->cur_xferlen = xferlen;
|
||||
|
||||
/* Disable the SPI hardware to unlock CFG1/CFG2 registers */
|
||||
stm32_spi_disable(priv);
|
||||
|
||||
clrsetbits_le32(priv->base + STM32_SPI_CFG2, SPI_CFG2_COMM,
|
||||
mode << SPI_CFG2_COMM_SHIFT);
|
||||
|
||||
stm32_spi_set_fthlv(bus, xferlen);
|
||||
|
||||
/* Enable the SPI hardware */
|
||||
stm32_spi_enable(priv);
|
||||
}
|
||||
|
||||
debug("%s: priv->tx_len=%d priv->rx_len=%d\n", __func__,
|
||||
priv->tx_len, priv->rx_len);
|
||||
|
||||
slave_plat = dev_get_parent_platdata(slave);
|
||||
if (flags & SPI_XFER_BEGIN)
|
||||
stm32_spi_set_cs(bus, slave_plat->cs, false);
|
||||
|
||||
/* Be sure to have data in fifo before starting data transfer */
|
||||
if (priv->tx_buf)
|
||||
stm32_spi_write_txfifo(priv);
|
||||
|
||||
setbits_le32(priv->base + STM32_SPI_CR1, SPI_CR1_CSTART);
|
||||
|
||||
while (1) {
|
||||
sr = readl(priv->base + STM32_SPI_SR);
|
||||
|
||||
if (sr & SPI_SR_OVR) {
|
||||
dev_err(bus, "Overrun: RX data lost\n");
|
||||
xfer_status = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sr & SPI_SR_SUSP) {
|
||||
dev_warn(bus, "System too slow is limiting data throughput\n");
|
||||
|
||||
if (priv->rx_buf && priv->rx_len > 0)
|
||||
stm32_spi_read_rxfifo(priv);
|
||||
|
||||
ifcr |= SPI_SR_SUSP;
|
||||
}
|
||||
|
||||
if (sr & SPI_SR_TXTF)
|
||||
ifcr |= SPI_SR_TXTF;
|
||||
|
||||
if (sr & SPI_SR_TXP)
|
||||
if (priv->tx_buf && priv->tx_len > 0)
|
||||
stm32_spi_write_txfifo(priv);
|
||||
|
||||
if (sr & SPI_SR_RXP)
|
||||
if (priv->rx_buf && priv->rx_len > 0)
|
||||
stm32_spi_read_rxfifo(priv);
|
||||
|
||||
if (sr & SPI_SR_EOT) {
|
||||
if (priv->rx_buf && priv->rx_len > 0)
|
||||
stm32_spi_read_rxfifo(priv);
|
||||
break;
|
||||
}
|
||||
|
||||
writel(ifcr, priv->base + STM32_SPI_IFCR);
|
||||
}
|
||||
|
||||
/* clear status flags */
|
||||
setbits_le32(priv->base + STM32_SPI_IFCR, SPI_IFCR_ALL);
|
||||
stm32_spi_stopxfer(bus);
|
||||
|
||||
if (flags & SPI_XFER_END)
|
||||
stm32_spi_set_cs(bus, slave_plat->cs, true);
|
||||
|
||||
return xfer_status;
|
||||
}
|
||||
|
||||
static int stm32_spi_get_fifo_size(struct udevice *dev)
|
||||
{
|
||||
struct stm32_spi_priv *priv = dev_get_priv(dev);
|
||||
u32 count = 0;
|
||||
|
||||
stm32_spi_enable(priv);
|
||||
|
||||
while (readl(priv->base + STM32_SPI_SR) & SPI_SR_TXP)
|
||||
writeb(++count, priv->base + STM32_SPI_TXDR);
|
||||
|
||||
stm32_spi_disable(priv);
|
||||
|
||||
debug("%s %d x 8-bit fifo size\n", __func__, count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int stm32_spi_probe(struct udevice *dev)
|
||||
{
|
||||
struct stm32_spi_priv *priv = dev_get_priv(dev);
|
||||
unsigned long clk_rate;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
priv->base = dev_remap_addr(dev);
|
||||
if (!priv->base)
|
||||
return -EINVAL;
|
||||
|
||||
/* enable clock */
|
||||
ret = clk_get_by_index(dev, 0, &priv->clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_enable(&priv->clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
clk_rate = clk_get_rate(&priv->clk);
|
||||
if (!clk_rate) {
|
||||
ret = -EINVAL;
|
||||
goto clk_err;
|
||||
}
|
||||
|
||||
priv->bus_clk_rate = clk_rate;
|
||||
|
||||
/* perform reset */
|
||||
ret = reset_get_by_index(dev, 0, &priv->rst_ctl);
|
||||
if (ret < 0)
|
||||
goto clk_err;
|
||||
|
||||
reset_assert(&priv->rst_ctl);
|
||||
udelay(2);
|
||||
reset_deassert(&priv->rst_ctl);
|
||||
|
||||
ret = gpio_request_list_by_name(dev, "cs-gpios", priv->cs_gpios,
|
||||
ARRAY_SIZE(priv->cs_gpios), 0);
|
||||
if (ret < 0) {
|
||||
pr_err("Can't get %s cs gpios: %d", dev->name, ret);
|
||||
goto reset_err;
|
||||
}
|
||||
|
||||
priv->fifo_size = stm32_spi_get_fifo_size(dev);
|
||||
|
||||
priv->cur_mode = SPI_FULL_DUPLEX;
|
||||
priv->cur_xferlen = 0;
|
||||
priv->cur_bpw = SPI_DEFAULT_WORDLEN;
|
||||
clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_DSIZE,
|
||||
priv->cur_bpw - 1);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(priv->cs_gpios); i++) {
|
||||
if (!dm_gpio_is_valid(&priv->cs_gpios[i]))
|
||||
continue;
|
||||
|
||||
dm_gpio_set_dir_flags(&priv->cs_gpios[i],
|
||||
GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
|
||||
}
|
||||
|
||||
/* Ensure I2SMOD bit is kept cleared */
|
||||
clrbits_le32(priv->base + STM32_SPI_I2SCFGR, SPI_I2SCFGR_I2SMOD);
|
||||
|
||||
/*
|
||||
* - SS input value high
|
||||
* - transmitter half duplex direction
|
||||
* - automatic communication suspend when RX-Fifo is full
|
||||
*/
|
||||
setbits_le32(priv->base + STM32_SPI_CR1,
|
||||
SPI_CR1_SSI | SPI_CR1_HDDIR | SPI_CR1_MASRX);
|
||||
|
||||
/*
|
||||
* - Set the master mode (default Motorola mode)
|
||||
* - Consider 1 master/n slaves configuration and
|
||||
* SS input value is determined by the SSI bit
|
||||
* - keep control of all associated GPIOs
|
||||
*/
|
||||
setbits_le32(priv->base + STM32_SPI_CFG2,
|
||||
SPI_CFG2_MASTER | SPI_CFG2_SSM | SPI_CFG2_AFCNTR);
|
||||
|
||||
return 0;
|
||||
|
||||
reset_err:
|
||||
reset_free(&priv->rst_ctl);
|
||||
|
||||
clk_err:
|
||||
clk_disable(&priv->clk);
|
||||
clk_free(&priv->clk);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
static int stm32_spi_remove(struct udevice *dev)
|
||||
{
|
||||
struct stm32_spi_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
stm32_spi_stopxfer(dev);
|
||||
stm32_spi_disable(priv);
|
||||
|
||||
ret = reset_assert(&priv->rst_ctl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
reset_free(&priv->rst_ctl);
|
||||
|
||||
ret = clk_disable(&priv->clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
clk_free(&priv->clk);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
static const struct dm_spi_ops stm32_spi_ops = {
|
||||
.claim_bus = stm32_spi_claim_bus,
|
||||
.release_bus = stm32_spi_release_bus,
|
||||
.set_mode = stm32_spi_set_mode,
|
||||
.set_speed = stm32_spi_set_speed,
|
||||
.xfer = stm32_spi_xfer,
|
||||
};
|
||||
|
||||
static const struct udevice_id stm32_spi_ids[] = {
|
||||
{ .compatible = "st,stm32h7-spi", },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stm32_spi) = {
|
||||
.name = "stm32_spi",
|
||||
.id = UCLASS_SPI,
|
||||
.of_match = stm32_spi_ids,
|
||||
.ops = &stm32_spi_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct stm32_spi_priv),
|
||||
.probe = stm32_spi_probe,
|
||||
.remove = stm32_spi_remove,
|
||||
};
|
@ -26,6 +26,13 @@ config BCM2835_WDT
|
||||
This provides basic infrastructure to support BCM2835/2836 watchdog
|
||||
hardware, with a max timeout of ~15secs.
|
||||
|
||||
config IMX_WATCHDOG
|
||||
bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP"
|
||||
select HW_WATCHDOG
|
||||
help
|
||||
Select this to enable the IMX and LSCH2 of Layerscape watchdog
|
||||
driver.
|
||||
|
||||
config OMAP_WATCHDOG
|
||||
bool "TI OMAP watchdog driver"
|
||||
depends on ARCH_OMAP2PLUS
|
||||
@ -59,14 +66,6 @@ config WDT
|
||||
What exactly happens when the timer expires is up to a particular
|
||||
device/driver.
|
||||
|
||||
config WDT_SANDBOX
|
||||
bool "Enable Watchdog Timer support for Sandbox"
|
||||
depends on SANDBOX && WDT
|
||||
help
|
||||
Enable Watchdog Timer support in Sandbox. This is a dummy device that
|
||||
can be probed and supports all of the methods of WDT, but does not
|
||||
really do anything.
|
||||
|
||||
config WDT_ARMADA_37XX
|
||||
bool "Marvell Armada 37xx watchdog timer support"
|
||||
depends on WDT && ARMADA_3700
|
||||
@ -87,6 +86,13 @@ config WDT_ASPEED
|
||||
It currently does not support Boot Flash Addressing Mode Detection or
|
||||
Second Boot.
|
||||
|
||||
config WDT_AT91
|
||||
bool "AT91 watchdog timer support"
|
||||
depends on WDT
|
||||
help
|
||||
Select this to enable Microchip watchdog timer, which can be found on
|
||||
some AT91 devices.
|
||||
|
||||
config WDT_BCM6345
|
||||
bool "BCM6345 watchdog timer support"
|
||||
depends on WDT && (ARCH_BMIPS || ARCH_BCM6858 || ARCH_BCM63158)
|
||||
@ -95,6 +101,36 @@ config WDT_BCM6345
|
||||
The watchdog timer is stopped when initialized.
|
||||
It performs full SoC reset.
|
||||
|
||||
config WDT_CDNS
|
||||
bool "Cadence watchdog timer support"
|
||||
depends on WDT
|
||||
imply WATCHDOG
|
||||
help
|
||||
Select this to enable Cadence watchdog timer, which can be found on some
|
||||
Xilinx Microzed Platform.
|
||||
|
||||
config WDT_MPC8xx
|
||||
bool "MPC8xx watchdog timer support"
|
||||
depends on WDT && MPC8xx
|
||||
select CONFIG_MPC8xx_WATCHDOG
|
||||
help
|
||||
Select this to enable mpc8xx watchdog timer
|
||||
|
||||
config WDT_MT7621
|
||||
bool "MediaTek MT7621 watchdog timer support"
|
||||
depends on WDT && SOC_MT7628
|
||||
help
|
||||
Select this to enable Ralink / Mediatek watchdog timer,
|
||||
which can be found on some MediaTek chips.
|
||||
|
||||
config WDT_MTK
|
||||
bool "MediaTek watchdog timer support"
|
||||
depends on WDT && ARCH_MEDIATEK
|
||||
help
|
||||
Select this to enable watchdog timer for MediaTek SoCs.
|
||||
The watchdog timer is stopped when initialized.
|
||||
It performs full SoC reset.
|
||||
|
||||
config WDT_ORION
|
||||
bool "Orion watchdog timer support"
|
||||
depends on WDT
|
||||
@ -103,6 +139,14 @@ config WDT_ORION
|
||||
Select this to enable Orion watchdog timer, which can be found on some
|
||||
Marvell Armada chips.
|
||||
|
||||
config WDT_SANDBOX
|
||||
bool "Enable Watchdog Timer support for Sandbox"
|
||||
depends on SANDBOX && WDT
|
||||
help
|
||||
Enable Watchdog Timer support in Sandbox. This is a dummy device that
|
||||
can be probed and supports all of the methods of WDT, but does not
|
||||
really do anything.
|
||||
|
||||
config WDT_SP805
|
||||
bool "SP805 watchdog timer support"
|
||||
depends on WDT
|
||||
@ -110,21 +154,13 @@ config WDT_SP805
|
||||
Select this to enable SP805 watchdog timer, which can be found on some
|
||||
nxp layerscape chips.
|
||||
|
||||
config WDT_CDNS
|
||||
bool "Cadence watchdog timer support"
|
||||
config WDT_STM32MP
|
||||
bool "IWDG watchdog driver for STM32 MP's family"
|
||||
depends on WDT
|
||||
imply WATCHDOG
|
||||
help
|
||||
Select this to enable Cadence watchdog timer, which can be found on some
|
||||
Xilinx Microzed Platform.
|
||||
|
||||
config WDT_MTK
|
||||
bool "MediaTek watchdog timer support"
|
||||
depends on WDT && ARCH_MEDIATEK
|
||||
help
|
||||
Select this to enable watchdog timer for MediaTek SoCs.
|
||||
The watchdog timer is stopped when initialized.
|
||||
It performs full SoC reset.
|
||||
Enable the STM32 watchdog (IWDG) driver. Enable support to
|
||||
configure STM32's on-SoC watchdog.
|
||||
|
||||
config XILINX_TB_WATCHDOG
|
||||
bool "Xilinx Axi watchdog timer support"
|
||||
@ -134,31 +170,4 @@ config XILINX_TB_WATCHDOG
|
||||
Select this to enable Xilinx Axi watchdog timer, which can be found on some
|
||||
Xilinx Microblaze Platforms.
|
||||
|
||||
config IMX_WATCHDOG
|
||||
bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP"
|
||||
select HW_WATCHDOG
|
||||
help
|
||||
Select this to enable the IMX and LSCH2 of Layerscape watchdog
|
||||
driver.
|
||||
|
||||
config WDT_AT91
|
||||
bool "AT91 watchdog timer support"
|
||||
depends on WDT
|
||||
help
|
||||
Select this to enable Microchip watchdog timer, which can be found on
|
||||
some AT91 devices.
|
||||
|
||||
config WDT_MT7621
|
||||
bool "MediaTek MT7621 watchdog timer support"
|
||||
depends on WDT && SOC_MT7628
|
||||
help
|
||||
Select this to enable Ralink / Mediatek watchdog timer,
|
||||
which can be found on some MediaTek chips.
|
||||
|
||||
config WDT_MPC8xx
|
||||
bool "MPC8xx watchdog timer support"
|
||||
depends on WDT && MPC8xx
|
||||
help
|
||||
Select this to enable mpc8xx watchdog timer
|
||||
|
||||
endmenu
|
||||
|
@ -28,3 +28,4 @@ obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
|
||||
obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
|
||||
obj-$(CONFIG_WDT_MTK) += mtk_wdt.o
|
||||
obj-$(CONFIG_WDT_SP805) += sp805_wdt.o
|
||||
obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o
|
||||
|
135
drivers/watchdog/stm32mp_wdt.c
Normal file
135
drivers/watchdog/stm32mp_wdt.c
Normal file
@ -0,0 +1,135 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2019, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <syscon.h>
|
||||
#include <wdt.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
/* IWDG registers */
|
||||
#define IWDG_KR 0x00 /* Key register */
|
||||
#define IWDG_PR 0x04 /* Prescaler Register */
|
||||
#define IWDG_RLR 0x08 /* ReLoad Register */
|
||||
#define IWDG_SR 0x0C /* Status Register */
|
||||
|
||||
/* IWDG_KR register bit mask */
|
||||
#define KR_KEY_RELOAD 0xAAAA /* Reload counter enable */
|
||||
#define KR_KEY_ENABLE 0xCCCC /* Peripheral enable */
|
||||
#define KR_KEY_EWA 0x5555 /* Write access enable */
|
||||
|
||||
/* IWDG_PR register bit values */
|
||||
#define PR_256 0x06 /* Prescaler set to 256 */
|
||||
|
||||
/* IWDG_RLR register values */
|
||||
#define RLR_MAX 0xFFF /* Max value supported by reload register */
|
||||
|
||||
/* IWDG_SR register bit values */
|
||||
#define SR_PVU BIT(0) /* Watchdog prescaler value update */
|
||||
#define SR_RVU BIT(1) /* Watchdog counter reload value update */
|
||||
|
||||
struct stm32mp_wdt_priv {
|
||||
fdt_addr_t base; /* registers addr in physical memory */
|
||||
unsigned long wdt_clk_rate; /* Watchdog dedicated clock rate */
|
||||
};
|
||||
|
||||
static int stm32mp_wdt_reset(struct udevice *dev)
|
||||
{
|
||||
struct stm32mp_wdt_priv *priv = dev_get_priv(dev);
|
||||
|
||||
writel(KR_KEY_RELOAD, priv->base + IWDG_KR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32mp_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
|
||||
{
|
||||
struct stm32mp_wdt_priv *priv = dev_get_priv(dev);
|
||||
int reload;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
/* Prescaler fixed to 256 */
|
||||
reload = timeout_ms * priv->wdt_clk_rate / 256;
|
||||
if (reload > RLR_MAX + 1)
|
||||
/* Force to max watchdog counter reload value */
|
||||
reload = RLR_MAX + 1;
|
||||
else if (!reload)
|
||||
/* Force to min watchdog counter reload value */
|
||||
reload = priv->wdt_clk_rate / 256;
|
||||
|
||||
/* Set prescaler & reload registers */
|
||||
writel(KR_KEY_EWA, priv->base + IWDG_KR);
|
||||
writel(PR_256, priv->base + IWDG_PR);
|
||||
writel(reload - 1, priv->base + IWDG_RLR);
|
||||
|
||||
/* Enable watchdog */
|
||||
writel(KR_KEY_ENABLE, priv->base + IWDG_KR);
|
||||
|
||||
/* Wait for the registers to be updated */
|
||||
ret = readl_poll_timeout(priv->base + IWDG_SR, val,
|
||||
val & (SR_PVU | SR_RVU), CONFIG_SYS_HZ);
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("Updating IWDG registers timeout");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32mp_wdt_probe(struct udevice *dev)
|
||||
{
|
||||
struct stm32mp_wdt_priv *priv = dev_get_priv(dev);
|
||||
struct clk clk;
|
||||
int ret;
|
||||
|
||||
debug("IWDG init\n");
|
||||
|
||||
priv->base = devfdt_get_addr(dev);
|
||||
if (priv->base == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
/* Enable clock */
|
||||
ret = clk_get_by_name(dev, "pclk", &clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_enable(&clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Get LSI clock */
|
||||
ret = clk_get_by_name(dev, "lsi", &clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->wdt_clk_rate = clk_get_rate(&clk);
|
||||
|
||||
debug("IWDG init done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct wdt_ops stm32mp_wdt_ops = {
|
||||
.start = stm32mp_wdt_start,
|
||||
.reset = stm32mp_wdt_reset,
|
||||
};
|
||||
|
||||
static const struct udevice_id stm32mp_wdt_match[] = {
|
||||
{ .compatible = "st,stm32mp1-iwdg" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stm32mp_wdt) = {
|
||||
.name = "stm32mp-wdt",
|
||||
.id = UCLASS_WDT,
|
||||
.of_match = stm32mp_wdt_match,
|
||||
.priv_auto_alloc_size = sizeof(struct stm32mp_wdt_priv),
|
||||
.probe = stm32mp_wdt_probe,
|
||||
.ops = &stm32mp_wdt_ops,
|
||||
};
|
18
env/Kconfig
vendored
18
env/Kconfig
vendored
@ -2,18 +2,12 @@ menu "Environment"
|
||||
|
||||
config ENV_IS_NOWHERE
|
||||
bool "Environment is not stored"
|
||||
depends on !ENV_IS_IN_EEPROM
|
||||
depends on !ENV_IS_IN_EXT4
|
||||
depends on !ENV_IS_IN_FAT
|
||||
depends on !ENV_IS_IN_FLASH
|
||||
depends on !ENV_IS_IN_MMC
|
||||
depends on !ENV_IS_IN_NAND
|
||||
depends on !ENV_IS_IN_NVRAM
|
||||
depends on !ENV_IS_IN_ONENAND
|
||||
depends on !ENV_IS_IN_REMOTE
|
||||
depends on !ENV_IS_IN_SPI_FLASH
|
||||
depends on !ENV_IS_IN_UBI
|
||||
default y
|
||||
default y if !ENV_IS_IN_EEPROM && !ENV_IS_IN_EXT4 && \
|
||||
!ENV_IS_IN_FAT && !ENV_IS_IN_FLASH && \
|
||||
!ENV_IS_IN_MMC && !ENV_IS_IN_NAND && \
|
||||
!ENV_IS_IN_NVRAM && !ENV_IS_IN_ONENAND && \
|
||||
!ENV_IS_IN_REMOTE && !ENV_IS_IN_SPI_FLASH && \
|
||||
!ENV_IS_IN_UBI
|
||||
help
|
||||
Define this if you don't want to or can't have an environment stored
|
||||
on a storage medium. In this case the environment will still exist
|
||||
|
34
env/ext4.c
vendored
34
env/ext4.c
vendored
@ -30,6 +30,16 @@
|
||||
#include <ext4fs.h>
|
||||
#include <mmc.h>
|
||||
|
||||
__weak const char *env_ext4_get_intf(void)
|
||||
{
|
||||
return (const char *)CONFIG_ENV_EXT4_INTERFACE;
|
||||
}
|
||||
|
||||
__weak const char *env_ext4_get_dev_part(void)
|
||||
{
|
||||
return (const char *)CONFIG_ENV_EXT4_DEVICE_AND_PART;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_SAVEENV
|
||||
static int env_ext4_save(void)
|
||||
{
|
||||
@ -38,13 +48,14 @@ static int env_ext4_save(void)
|
||||
disk_partition_t info;
|
||||
int dev, part;
|
||||
int err;
|
||||
const char *ifname = env_ext4_get_intf();
|
||||
const char *dev_and_part = env_ext4_get_dev_part();
|
||||
|
||||
err = env_export(&env_new);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
part = blk_get_device_part_str(CONFIG_ENV_EXT4_INTERFACE,
|
||||
CONFIG_ENV_EXT4_DEVICE_AND_PART,
|
||||
part = blk_get_device_part_str(ifname, dev_and_part,
|
||||
&dev_desc, &info, 1);
|
||||
if (part < 0)
|
||||
return 1;
|
||||
@ -54,8 +65,7 @@ static int env_ext4_save(void)
|
||||
|
||||
if (!ext4fs_mount(info.size)) {
|
||||
printf("\n** Unable to use %s %s for saveenv **\n",
|
||||
CONFIG_ENV_EXT4_INTERFACE,
|
||||
CONFIG_ENV_EXT4_DEVICE_AND_PART);
|
||||
ifname, dev_and_part);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -65,8 +75,7 @@ static int env_ext4_save(void)
|
||||
|
||||
if (err == -1) {
|
||||
printf("\n** Unable to write \"%s\" from %s%d:%d **\n",
|
||||
CONFIG_ENV_EXT4_FILE, CONFIG_ENV_EXT4_INTERFACE, dev,
|
||||
part);
|
||||
CONFIG_ENV_EXT4_FILE, ifname, dev, part);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -83,14 +92,15 @@ static int env_ext4_load(void)
|
||||
int dev, part;
|
||||
int err;
|
||||
loff_t off;
|
||||
const char *ifname = env_ext4_get_intf();
|
||||
const char *dev_and_part = env_ext4_get_dev_part();
|
||||
|
||||
#ifdef CONFIG_MMC
|
||||
if (!strcmp(CONFIG_ENV_EXT4_INTERFACE, "mmc"))
|
||||
if (!strcmp(ifname, "mmc"))
|
||||
mmc_initialize(NULL);
|
||||
#endif
|
||||
|
||||
part = blk_get_device_part_str(CONFIG_ENV_EXT4_INTERFACE,
|
||||
CONFIG_ENV_EXT4_DEVICE_AND_PART,
|
||||
part = blk_get_device_part_str(ifname, dev_and_part,
|
||||
&dev_desc, &info, 1);
|
||||
if (part < 0)
|
||||
goto err_env_relocate;
|
||||
@ -100,8 +110,7 @@ static int env_ext4_load(void)
|
||||
|
||||
if (!ext4fs_mount(info.size)) {
|
||||
printf("\n** Unable to use %s %s for loading the env **\n",
|
||||
CONFIG_ENV_EXT4_INTERFACE,
|
||||
CONFIG_ENV_EXT4_DEVICE_AND_PART);
|
||||
ifname, dev_and_part);
|
||||
goto err_env_relocate;
|
||||
}
|
||||
|
||||
@ -111,8 +120,7 @@ static int env_ext4_load(void)
|
||||
|
||||
if (err == -1) {
|
||||
printf("\n** Unable to read \"%s\" from %s%d:%d **\n",
|
||||
CONFIG_ENV_EXT4_FILE, CONFIG_ENV_EXT4_INTERFACE, dev,
|
||||
part);
|
||||
CONFIG_ENV_EXT4_FILE, ifname, dev, part);
|
||||
goto err_env_relocate;
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,15 @@
|
||||
*/
|
||||
#define CONFIG_SYS_LOAD_ADDR STM32_DDR_BASE
|
||||
|
||||
#if defined(CONFIG_ENV_IS_IN_UBI)
|
||||
#define CONFIG_ENV_UBI_VOLUME_REDUND "uboot_config_r"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ENV_IS_IN_SPI_FLASH)
|
||||
#define CONFIG_ENV_SECT_SIZE SZ_256K
|
||||
#define CONFIG_ENV_OFFSET 0x00280000
|
||||
#endif
|
||||
|
||||
/* ATAGs */
|
||||
#define CONFIG_CMDLINE_TAG
|
||||
#define CONFIG_SETUP_MEMORY_TAGS
|
||||
@ -68,16 +77,29 @@
|
||||
/*MMC SD*/
|
||||
#define CONFIG_SYS_MMC_MAX_DEVICE 3
|
||||
|
||||
/* Ethernet need */
|
||||
#ifdef CONFIG_DWC_ETH_QOS
|
||||
#define CONFIG_SYS_NONCACHED_MEMORY (1 * SZ_1M) /* 1M */
|
||||
#define CONFIG_SERVERIP 192.168.1.1
|
||||
#define CONFIG_BOOTP_SERVERIP
|
||||
#define CONFIG_SYS_AUTOLOAD "no"
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
#ifdef CONFIG_DISTRO_DEFAULTS
|
||||
/*****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_SPL_BUILD)
|
||||
|
||||
/* NAND support */
|
||||
#define CONFIG_SYS_NAND_ONFI_DETECTION
|
||||
#define CONFIG_SYS_MAX_NAND_DEVICE 1
|
||||
#define BOOT_TARGET_DEVICES(func) \
|
||||
func(MMC, mmc, 1) \
|
||||
func(MMC, mmc, 0) \
|
||||
func(MMC, mmc, 2)
|
||||
func(MMC, mmc, 2) \
|
||||
func(PXE, pxe, na)
|
||||
|
||||
/*
|
||||
* bootcmd for stm32mp1:
|
||||
* for serial/usb: execute the stm32prog command
|
||||
@ -99,6 +121,14 @@
|
||||
|
||||
#include <config_distro_bootcmd.h>
|
||||
|
||||
#if defined(CONFIG_STM32_QSPI) || defined(CONFIG_NAND_STM32_FMC)
|
||||
#define CONFIG_SYS_MTDPARTS_RUNTIME
|
||||
#endif
|
||||
|
||||
#define STM32MP_MTDPARTS \
|
||||
"mtdparts_nor0=256k(fsbl1),256k(fsbl2),2m(ssbl),256k(u-boot-env),-(nor_user)\0" \
|
||||
"mtdparts_nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),-(UBI)\0"
|
||||
|
||||
/*
|
||||
* memory layout for 32M uncompressed/compressed kernel,
|
||||
* 1M fdt, 1M script, 1M pxe and 1M for splashimage
|
||||
@ -114,6 +144,7 @@
|
||||
"fdt_high=0xffffffff\0" \
|
||||
"initrd_high=0xffffffff\0" \
|
||||
STM32MP_BOOTCMD \
|
||||
STM32MP_MTDPARTS \
|
||||
BOOTENV
|
||||
|
||||
#endif /* ifndef CONFIG_SPL_BUILD */
|
||||
|
Loading…
Reference in New Issue
Block a user