mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
stm32 patches for v2019.07-rc1
- Add trusted boot with TF-A for stm32mp1 - stm32mp1 dts files sync'ed with Linux version - add STM32MP1 Discovery boards (DK1 and DK2) - add STMFX gpio expander driver - misc improvement for stm3mp1 supports - rename stpmu1 to stpmic1 (official name) - stm32_qspi: move to exec_op (spi nor driver for stm32 mpu and mcu) - add STM32 FMC2 NAND flash controller driver -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJcsLHKAAoJEOKyvdngqpN1iwsH/3HtFxWsIcmT8TfHgIi2USKx /Rpj5Mdl0Q0584LAxZXkR2m9YvzBU6n2tR/n9wQfRyiazoEps1LXMmYcZVy35mQg AjTNV7xWfC1EZFP0+Gvn5PFquMPoZoIeqbDy1Jk91Qr4CHIqqS64DBwlTmQfjLzf 6vfoyBcheL5Rf/AGM5AaHMjwh1GZs89cBCeVjGVMUAPgbfFUAKBWwi2fqdgEbDD7 b9owLl2IykLTHOhvfnZi5NeRoA39deuNB0vSfU4WcMcONhekFCfOPi3Hch5aM/os xXlAXkTqps8rVfYHvUUmHm/wJhk+HH69wMThAWNFev/3g94MWR5zen5rjIOBVGg= =9M63 -----END PGP SIGNATURE----- Merge tag 'u-boot-stm32-20190412' of https://github.com/patrickdelaunay/u-boot stm32 patches for v2019.07-rc1 - Add trusted boot with TF-A for stm32mp1 - stm32mp1 dts files sync'ed with Linux version - add STM32MP1 Discovery boards (DK1 and DK2) - add STMFX gpio expander driver - misc improvement for stm3mp1 supports - rename stpmu1 to stpmic1 (official name) - stm32_qspi: move to exec_op (spi nor driver for stm32 mpu and mcu) - add STM32 FMC2 NAND flash controller driver
This commit is contained in:
commit
015289580f
59 changed files with 5301 additions and 1563 deletions
|
@ -295,7 +295,9 @@ F: drivers/misc/stm32mp_fuse.c
|
|||
F: drivers/mmc/stm32_sdmmc2.c
|
||||
F: drivers/phy/phy-stm32-usbphyc.c
|
||||
F: drivers/pinctrl/pinctrl_stm32.c
|
||||
F: drivers/power/pmic/stpmic1.c
|
||||
F: drivers/power/regulator/stm32-vrefbuf.c
|
||||
F: drivers/power/regulator/stpmic1.c
|
||||
F: drivers/ram/stm32mp1/
|
||||
F: drivers/misc/stm32_rcc.c
|
||||
F: drivers/reset/stm32-reset.c
|
||||
|
|
|
@ -1403,11 +1403,15 @@ config ARCH_STM32MP
|
|||
select SYSRESET
|
||||
select SYS_THUMB_BUILD
|
||||
imply CMD_DM
|
||||
imply CMD_POWEROFF
|
||||
imply ENV_VARS_UBOOT_RUNTIME_CONFIG
|
||||
help
|
||||
Support for STM32MP SoC family developed by STMicroelectronics,
|
||||
MPUs based on ARM cortex A core
|
||||
U-BOOT is running in DDR and SPL support is the unsecure First Stage
|
||||
BootLoader (FSBL)
|
||||
U-BOOT is running in DDR, loaded by the First Stage BootLoader (FSBL).
|
||||
FSBL can be TF-A: Trusted Firmware for Cortex A, for trusted boot
|
||||
chain.
|
||||
SPL is the unsecure FSBL for the basic boot chain.
|
||||
|
||||
config ARCH_ROCKCHIP
|
||||
bool "Support Rockchip SoCs"
|
||||
|
|
|
@ -688,6 +688,8 @@ dtb-$(CONFIG_ARCH_ASPEED) += ast2500-evb.dtb
|
|||
dtb-$(CONFIG_ARCH_STI) += stih410-b2260.dtb
|
||||
|
||||
dtb-$(CONFIG_TARGET_STM32MP1) += \
|
||||
stm32mp157a-dk1.dtb \
|
||||
stm32mp157c-dk2.dtb \
|
||||
stm32mp157c-ed1.dtb \
|
||||
stm32mp157c-ev1.dtb
|
||||
|
||||
|
|
120
arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
Normal file
120
arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
Normal file
|
@ -0,0 +1,120 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* STM32MP157C DK1/DK2 BOARD configuration
|
||||
* 1x DDR3L 4Gb, 16-bit, 533MHz.
|
||||
* Reference used NT5CC256M16DP-DI from NANYA
|
||||
*
|
||||
* DDR type / Platform DDR3/3L
|
||||
* freq 533MHz
|
||||
* width 16
|
||||
* datasheet 0 = MT41J256M16-187 / DDR3-1066 bin G
|
||||
* DDR density 4
|
||||
* timing mode optimized
|
||||
* Scheduling/QoS options : type = 2
|
||||
* address mapping : RBC
|
||||
* Tc > + 85C : N
|
||||
*/
|
||||
#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.43"
|
||||
#define DDR_MEM_SPEED 533
|
||||
#define DDR_MEM_SIZE 0x20000000
|
||||
|
||||
#define DDR_MSTR 0x00041401
|
||||
#define DDR_MRCTRL0 0x00000010
|
||||
#define DDR_MRCTRL1 0x00000000
|
||||
#define DDR_DERATEEN 0x00000000
|
||||
#define DDR_DERATEINT 0x00800000
|
||||
#define DDR_PWRCTL 0x00000000
|
||||
#define DDR_PWRTMG 0x00400010
|
||||
#define DDR_HWLPCTL 0x00000000
|
||||
#define DDR_RFSHCTL0 0x00210000
|
||||
#define DDR_RFSHCTL3 0x00000000
|
||||
#define DDR_RFSHTMG 0x0081008B
|
||||
#define DDR_CRCPARCTL0 0x00000000
|
||||
#define DDR_DRAMTMG0 0x121B2414
|
||||
#define DDR_DRAMTMG1 0x000A041C
|
||||
#define DDR_DRAMTMG2 0x0608090F
|
||||
#define DDR_DRAMTMG3 0x0050400C
|
||||
#define DDR_DRAMTMG4 0x08040608
|
||||
#define DDR_DRAMTMG5 0x06060403
|
||||
#define DDR_DRAMTMG6 0x02020002
|
||||
#define DDR_DRAMTMG7 0x00000202
|
||||
#define DDR_DRAMTMG8 0x00001005
|
||||
#define DDR_DRAMTMG14 0x000000A0
|
||||
#define DDR_ZQCTL0 0xC2000040
|
||||
#define DDR_DFITMG0 0x02060105
|
||||
#define DDR_DFITMG1 0x00000202
|
||||
#define DDR_DFILPCFG0 0x07000000
|
||||
#define DDR_DFIUPD0 0xC0400003
|
||||
#define DDR_DFIUPD1 0x00000000
|
||||
#define DDR_DFIUPD2 0x00000000
|
||||
#define DDR_DFIPHYMSTR 0x00000000
|
||||
#define DDR_ADDRMAP1 0x00070707
|
||||
#define DDR_ADDRMAP2 0x00000000
|
||||
#define DDR_ADDRMAP3 0x1F000000
|
||||
#define DDR_ADDRMAP4 0x00001F1F
|
||||
#define DDR_ADDRMAP5 0x06060606
|
||||
#define DDR_ADDRMAP6 0x0F060606
|
||||
#define DDR_ADDRMAP9 0x00000000
|
||||
#define DDR_ADDRMAP10 0x00000000
|
||||
#define DDR_ADDRMAP11 0x00000000
|
||||
#define DDR_ODTCFG 0x06000600
|
||||
#define DDR_ODTMAP 0x00000001
|
||||
#define DDR_SCHED 0x00000C01
|
||||
#define DDR_SCHED1 0x00000000
|
||||
#define DDR_PERFHPR1 0x01000001
|
||||
#define DDR_PERFLPR1 0x08000200
|
||||
#define DDR_PERFWR1 0x08000400
|
||||
#define DDR_DBG0 0x00000000
|
||||
#define DDR_DBG1 0x00000000
|
||||
#define DDR_DBGCMD 0x00000000
|
||||
#define DDR_POISONCFG 0x00000000
|
||||
#define DDR_PCCFG 0x00000010
|
||||
#define DDR_PCFGR_0 0x00010000
|
||||
#define DDR_PCFGW_0 0x00000000
|
||||
#define DDR_PCFGQOS0_0 0x02100C03
|
||||
#define DDR_PCFGQOS1_0 0x00800100
|
||||
#define DDR_PCFGWQOS0_0 0x01100C03
|
||||
#define DDR_PCFGWQOS1_0 0x01000200
|
||||
#define DDR_PCFGR_1 0x00010000
|
||||
#define DDR_PCFGW_1 0x00000000
|
||||
#define DDR_PCFGQOS0_1 0x02100C03
|
||||
#define DDR_PCFGQOS1_1 0x00800040
|
||||
#define DDR_PCFGWQOS0_1 0x01100C03
|
||||
#define DDR_PCFGWQOS1_1 0x01000200
|
||||
#define DDR_PGCR 0x01442E02
|
||||
#define DDR_PTR0 0x0022AA5B
|
||||
#define DDR_PTR1 0x04841104
|
||||
#define DDR_PTR2 0x042DA068
|
||||
#define DDR_ACIOCR 0x10400812
|
||||
#define DDR_DXCCR 0x00000C40
|
||||
#define DDR_DSGCR 0xF200001F
|
||||
#define DDR_DCR 0x0000000B
|
||||
#define DDR_DTPR0 0x38D488D0
|
||||
#define DDR_DTPR1 0x098B00D8
|
||||
#define DDR_DTPR2 0x10023600
|
||||
#define DDR_MR0 0x00000840
|
||||
#define DDR_MR1 0x00000000
|
||||
#define DDR_MR2 0x00000208
|
||||
#define DDR_MR3 0x00000000
|
||||
#define DDR_ODTCR 0x00010000
|
||||
#define DDR_ZQ0CR1 0x00000038
|
||||
#define DDR_DX0GCR 0x0000CE81
|
||||
#define DDR_DX0DLLCR 0x40000000
|
||||
#define DDR_DX0DQTR 0xFFFFFFFF
|
||||
#define DDR_DX0DQSTR 0x3DB02000
|
||||
#define DDR_DX1GCR 0x0000CE81
|
||||
#define DDR_DX1DLLCR 0x40000000
|
||||
#define DDR_DX1DQTR 0xFFFFFFFF
|
||||
#define DDR_DX1DQSTR 0x3DB02000
|
||||
#define DDR_DX2GCR 0x0000CE81
|
||||
#define DDR_DX2DLLCR 0x40000000
|
||||
#define DDR_DX2DQTR 0xFFFFFFFF
|
||||
#define DDR_DX2DQSTR 0x3DB02000
|
||||
#define DDR_DX3GCR 0x0000CE81
|
||||
#define DDR_DX3DLLCR 0x40000000
|
||||
#define DDR_DX3DQTR 0xFFFFFFFF
|
||||
#define DDR_DX3DQSTR 0x3DB02000
|
||||
|
||||
#include "stm32mp15-ddr.dtsi"
|
|
@ -148,6 +148,13 @@
|
|||
gpio-ranges = <&pinctrl 0 160 8>;
|
||||
};
|
||||
|
||||
adc12_usb_pwr_pins_a: adc12-usb-pwr-pins-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('A', 4, ANALOG)>, /* ADC12 in18 */
|
||||
<STM32_PINMUX('A', 5, ANALOG)>; /* ADC12 in19 */
|
||||
};
|
||||
};
|
||||
|
||||
cec_pins_a: cec-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('A', 15, AF4)>;
|
||||
|
@ -157,6 +164,52 @@
|
|||
};
|
||||
};
|
||||
|
||||
ethernet0_rgmii_pins_a: rgmii-0 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
|
||||
<STM32_PINMUX('G', 4, AF11)>, /* ETH_RGMII_GTX_CLK */
|
||||
<STM32_PINMUX('G', 13, AF11)>, /* ETH_RGMII_TXD0 */
|
||||
<STM32_PINMUX('G', 14, AF11)>, /* ETH_RGMII_TXD1 */
|
||||
<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>;
|
||||
};
|
||||
pins2 {
|
||||
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 */
|
||||
<STM32_PINMUX('B', 1, AF11)>, /* ETH_RGMII_RXD3 */
|
||||
<STM32_PINMUX('A', 1, AF11)>, /* ETH_RGMII_RX_CLK */
|
||||
<STM32_PINMUX('A', 7, AF11)>; /* ETH_RGMII_RX_CTL */
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
ethernet0_rgmii_pins_sleep_a: rgmii-sleep-0 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */
|
||||
<STM32_PINMUX('G', 4, ANALOG)>, /* ETH_RGMII_GTX_CLK */
|
||||
<STM32_PINMUX('G', 13, ANALOG)>, /* ETH_RGMII_TXD0 */
|
||||
<STM32_PINMUX('G', 14, ANALOG)>, /* ETH_RGMII_TXD1 */
|
||||
<STM32_PINMUX('C', 2, ANALOG)>, /* ETH_RGMII_TXD2 */
|
||||
<STM32_PINMUX('E', 2, ANALOG)>, /* ETH_RGMII_TXD3 */
|
||||
<STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RGMII_TX_CTL */
|
||||
<STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */
|
||||
<STM32_PINMUX('C', 1, ANALOG)>, /* ETH_MDC */
|
||||
<STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_RXD0 */
|
||||
<STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RGMII_RXD1 */
|
||||
<STM32_PINMUX('B', 0, ANALOG)>, /* ETH_RGMII_RXD2 */
|
||||
<STM32_PINMUX('B', 1, ANALOG)>, /* ETH_RGMII_RXD3 */
|
||||
<STM32_PINMUX('A', 1, ANALOG)>, /* ETH_RGMII_RX_CLK */
|
||||
<STM32_PINMUX('A', 7, ANALOG)>; /* ETH_RGMII_RX_CTL */
|
||||
};
|
||||
};
|
||||
|
||||
i2c1_pins_a: i2c1-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */
|
||||
|
@ -187,6 +240,19 @@
|
|||
};
|
||||
};
|
||||
|
||||
m_can1_pins_a: m-can1-0 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
|
||||
slew-rate = <1>;
|
||||
drive-push-pull;
|
||||
bias-disable;
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('I', 9, AF9)>; /* CAN1_RX */
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
pwm2_pins_a: pwm2-0 {
|
||||
pins {
|
||||
pinmux = <STM32_PINMUX('A', 3, AF1)>; /* TIM2_CH4 */
|
||||
|
@ -360,6 +426,21 @@
|
|||
slew-rate = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
spi1_pins_a: spi1-0 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('Z', 0, AF5)>, /* SPI1_SCK */
|
||||
<STM32_PINMUX('Z', 2, AF5)>; /* SPI1_MOSI */
|
||||
bias-disable;
|
||||
drive-push-pull;
|
||||
slew-rate = <1>;
|
||||
};
|
||||
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('Z', 1, AF5)>; /* SPI1_MISO */
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
gpio9 = &gpioj;
|
||||
gpio10 = &gpiok;
|
||||
gpio25 = &gpioz;
|
||||
pinctrl0 = &pinctrl;
|
||||
pinctrl1 = &pinctrl_z;
|
||||
};
|
||||
|
||||
config {
|
||||
|
@ -39,6 +41,10 @@
|
|||
};
|
||||
};
|
||||
|
||||
&bsec {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
&clk_hsi {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
|
199
arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
Normal file
199
arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
Normal file
|
@ -0,0 +1,199 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright : STMicroelectronics 2018
|
||||
*/
|
||||
|
||||
#include <dt-bindings/clock/stm32mp1-clksrc.h>
|
||||
#include "stm32mp157-u-boot.dtsi"
|
||||
#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi"
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
i2c3 = &i2c4;
|
||||
mmc0 = &sdmmc1;
|
||||
};
|
||||
config {
|
||||
u-boot,boot-led = "heartbeat";
|
||||
u-boot,error-led = "error";
|
||||
st,adc_usb_pd = <&adc1 18>, <&adc1 19>;
|
||||
};
|
||||
led {
|
||||
red {
|
||||
label = "error";
|
||||
gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
|
||||
default-state = "off";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
blue {
|
||||
default-state = "on";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&adc {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&adc12_usb_pwr_pins_a>;
|
||||
vdd-supply = <&vdd>;
|
||||
vdda-supply = <&vdd>;
|
||||
vref-supply = <&vrefbuf>;
|
||||
status = "okay";
|
||||
adc1: adc@0 {
|
||||
/*
|
||||
* Type-C USB_PWR_CC1 & USB_PWR_CC2 on in18 & in19.
|
||||
* Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C:
|
||||
* 5 * (56 + 47kOhms) * 5pF => 2.5us.
|
||||
* Use arbitrary margin here (e.g. 5µs).
|
||||
*/
|
||||
st,min-sample-time-nsecs = <5000>;
|
||||
/* ANA0, ANA1, USB Type-C CC1 & CC2 */
|
||||
st,adc-channels = <0 1 18 19>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
&clk_hse {
|
||||
st,digbypass;
|
||||
};
|
||||
|
||||
&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 = 594.0 MHz => P = 99, Q = 74, R = 74 */
|
||||
pll4: st,pll@3 {
|
||||
cfg = < 3 98 5 7 7 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;
|
||||
};
|
||||
};
|
||||
|
||||
&uart4 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
&uart4_pins_a {
|
||||
u-boot,dm-pre-reloc;
|
||||
pins1 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
pins2 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
};
|
||||
|
||||
&usbotg_hs {
|
||||
usb1600;
|
||||
hnp-srp-disable;
|
||||
};
|
||||
|
||||
&v3v3 {
|
||||
regulator-always-on;
|
||||
};
|
262
arch/arm/dts/stm32mp157a-dk1.dts
Normal file
262
arch/arm/dts/stm32mp157a-dk1.dts
Normal file
|
@ -0,0 +1,262 @@
|
|||
// 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.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "stm32mp157c.dtsi"
|
||||
#include "stm32mp157-pinctrl.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/mfd/st,stpmic1.h>
|
||||
|
||||
/ {
|
||||
model = "STMicroelectronics STM32MP157A-DK1 Discovery Board";
|
||||
compatible = "st,stm32mp157a-dk1", "st,stm32mp157";
|
||||
|
||||
aliases {
|
||||
ethernet0 = ðernet0;
|
||||
serial0 = &uart4;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
memory@c0000000 {
|
||||
reg = <0xc0000000 0x20000000>;
|
||||
};
|
||||
|
||||
led {
|
||||
compatible = "gpio-leds";
|
||||
blue {
|
||||
label = "heartbeat";
|
||||
gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
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@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&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>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
status = "okay";
|
||||
|
||||
st,main-control-register = <0x04>;
|
||||
st,vin-control-register = <0xc0>;
|
||||
st,usb-control-register = <0x20>;
|
||||
|
||||
regulators {
|
||||
compatible = "st,stpmic1-regulators";
|
||||
|
||||
ldo1-supply = <&v3v3>;
|
||||
ldo3-supply = <&vdd_ddr>;
|
||||
ldo6-supply = <&v3v3>;
|
||||
pwr_sw1-supply = <&bst_out>;
|
||||
pwr_sw2-supply = <&bst_out>;
|
||||
|
||||
vddcore: buck1 {
|
||||
regulator-name = "vddcore";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-always-on;
|
||||
regulator-initial-mode = <0>;
|
||||
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 = <0>;
|
||||
regulator-over-current-protection;
|
||||
};
|
||||
|
||||
vdd: buck3 {
|
||||
regulator-name = "vdd";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
st,mask-reset;
|
||||
regulator-initial-mode = <0>;
|
||||
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 = <0>;
|
||||
};
|
||||
|
||||
v1v8_audio: ldo1 {
|
||||
regulator-name = "v1v8_audio";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-always-on;
|
||||
interrupts = <IT_CURLIM_LDO1 0>;
|
||||
};
|
||||
|
||||
v3v3_hdmi: ldo2 {
|
||||
regulator-name = "v3v3_hdmi";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
interrupts = <IT_CURLIM_LDO2 0>;
|
||||
};
|
||||
|
||||
vtt_ddr: ldo3 {
|
||||
regulator-name = "vtt_ddr";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <750000>;
|
||||
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>;
|
||||
};
|
||||
|
||||
vdda: ldo5 {
|
||||
regulator-name = "vdda";
|
||||
regulator-min-microvolt = <2900000>;
|
||||
regulator-max-microvolt = <2900000>;
|
||||
interrupts = <IT_CURLIM_LDO5 0>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
v1v2_hdmi: ldo6 {
|
||||
regulator-name = "v1v2_hdmi";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-always-on;
|
||||
interrupts = <IT_CURLIM_LDO6 0>;
|
||||
|
||||
};
|
||||
|
||||
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>;
|
||||
};
|
||||
|
||||
vbus_otg: pwr_sw1 {
|
||||
regulator-name = "vbus_otg";
|
||||
interrupts = <IT_OCP_OTG 0>;
|
||||
regulator-active-discharge;
|
||||
};
|
||||
|
||||
vbus_sw: pwr_sw2 {
|
||||
regulator-name = "vbus_sw";
|
||||
interrupts = <IT_OCP_SWOUT 0>;
|
||||
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>;
|
||||
broken-cd;
|
||||
st,neg-edge;
|
||||
bus-width = <4>;
|
||||
vmmc-supply = <&v3v3>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart4 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart4_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usbh_ehci {
|
||||
phys = <&usbphyc_port0>;
|
||||
phy-names = "usb";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usbphyc {
|
||||
vdd3v3-supply = <&vdd_usb>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vrefbuf {
|
||||
regulator-min-microvolt = <2500000>;
|
||||
regulator-max-microvolt = <2500000>;
|
||||
vdda-supply = <&vdd>;
|
||||
status = "okay";
|
||||
};
|
6
arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
Normal file
6
arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
Normal file
|
@ -0,0 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright : STMicroelectronics 2018
|
||||
*/
|
||||
|
||||
#include "stm32mp157a-dk1-u-boot.dtsi"
|
67
arch/arm/dts/stm32mp157c-dk2.dts
Normal file
67
arch/arm/dts/stm32mp157c-dk2.dts
Normal file
|
@ -0,0 +1,67 @@
|
|||
// 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.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "stm32mp157a-dk1.dts"
|
||||
|
||||
/ {
|
||||
model = "STMicroelectronics STM32MP157C-DK2 Discovery Board";
|
||||
compatible = "st,stm32mp157c-dk2", "st,stm32mp157";
|
||||
};
|
||||
|
||||
&dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
phy-dsi-supply = <®18>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dsi_in: endpoint {
|
||||
remote-endpoint = <<dc_ep1_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
dsi_out: endpoint {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
panel@0 {
|
||||
compatible = "orisetech,otm8009a";
|
||||
reg = <0>;
|
||||
reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>;
|
||||
status = "okay";
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dsi_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
<dc {
|
||||
status = "okay";
|
||||
|
||||
port {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ltdc_ep1_out: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&dsi_in>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -9,9 +9,14 @@
|
|||
|
||||
/ {
|
||||
aliases {
|
||||
i2c3 = &i2c4;
|
||||
mmc0 = &sdmmc1;
|
||||
mmc1 = &sdmmc2;
|
||||
i2c3 = &i2c4;
|
||||
};
|
||||
|
||||
config {
|
||||
st,fastboot-gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
|
||||
st,stm32prog-gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
led {
|
||||
|
@ -43,14 +48,8 @@
|
|||
st,digbypass;
|
||||
};
|
||||
|
||||
&uart4_pins_a {
|
||||
&i2c4 {
|
||||
u-boot,dm-pre-reloc;
|
||||
pins1 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
pins2 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c4_pins_a {
|
||||
|
@ -60,14 +59,6 @@
|
|||
};
|
||||
};
|
||||
|
||||
&uart4 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
&i2c4 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
&pmic {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
@ -165,8 +156,6 @@
|
|||
};
|
||||
};
|
||||
|
||||
/* SPL part **************************************/
|
||||
/* MMC1 boot */
|
||||
&sdmmc1_b4_pins_a {
|
||||
u-boot,dm-spl;
|
||||
pins {
|
||||
|
@ -185,7 +174,6 @@
|
|||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
/* MMC2 boot */
|
||||
&sdmmc2_b4_pins_a {
|
||||
u-boot,dm-spl;
|
||||
pins {
|
||||
|
@ -203,3 +191,17 @@
|
|||
&sdmmc2 {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&uart4 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
&uart4_pins_a {
|
||||
u-boot,dm-pre-reloc;
|
||||
pins1 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
pins2 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -8,20 +8,24 @@
|
|||
#include "stm32mp157c.dtsi"
|
||||
#include "stm32mp157-pinctrl.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/mfd/st,stpmu1.h>
|
||||
#include <dt-bindings/mfd/st,stpmic1.h>
|
||||
|
||||
/ {
|
||||
model = "STMicroelectronics STM32MP157C eval daughter";
|
||||
compatible = "st,stm32mp157c-ed1", "st,stm32mp157";
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial3:115200n8";
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
memory@c0000000 {
|
||||
reg = <0xC0000000 0x40000000>;
|
||||
};
|
||||
|
||||
aliases {
|
||||
serial0 = &uart4;
|
||||
};
|
||||
|
||||
sd_switch: regulator-sd_switch {
|
||||
compatible = "regulator-gpio";
|
||||
regulator-name = "sd_switch";
|
||||
|
@ -36,17 +40,10 @@
|
|||
};
|
||||
};
|
||||
|
||||
&rng1 {
|
||||
&hwspinlock {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&timers6 {
|
||||
status = "okay";
|
||||
timer@5 {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
&i2c4 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c4_pins_a>;
|
||||
|
@ -54,8 +51,8 @@
|
|||
i2c-scl-falling-time-ns = <20>;
|
||||
status = "okay";
|
||||
|
||||
pmic: stpmu1@33 {
|
||||
compatible = "st,stpmu1";
|
||||
pmic: stpmic1@33 {
|
||||
compatible = "st,stpmic1";
|
||||
reg = <0x33>;
|
||||
interrupts = <0 2>;
|
||||
interrupt-parent = <&gpioa>;
|
||||
|
@ -68,7 +65,7 @@
|
|||
st,usb_control_register = <0x30>;
|
||||
|
||||
regulators {
|
||||
compatible = "st,stpmu1-regulators";
|
||||
compatible = "st,stpmic1-regulators";
|
||||
|
||||
ldo1-supply = <&v3v3>;
|
||||
ldo2-supply = <&v3v3>;
|
||||
|
@ -321,10 +318,27 @@
|
|||
};
|
||||
};
|
||||
|
||||
&iwdg2 {
|
||||
timeout-sec = <32>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
hwlocks = <&hwspinlock 0>;
|
||||
};
|
||||
|
||||
&pwr {
|
||||
pwr-supply = <&vdd>;
|
||||
};
|
||||
|
||||
&rng1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rtc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdmmc1 {
|
||||
pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
|
||||
broken-cd;
|
||||
|
@ -355,6 +369,13 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
&timers6 {
|
||||
status = "okay";
|
||||
timer@5 {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
&uart4 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart4_pins_a>;
|
||||
|
@ -365,14 +386,6 @@
|
|||
usb33d-supply = <&usb33>;
|
||||
};
|
||||
|
||||
&hwspinlock {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
hwlocks = <&hwspinlock 0>;
|
||||
};
|
||||
|
||||
&usbphyc_port0 {
|
||||
phy-supply = <&vdd_usb>;
|
||||
vdda1v1-supply = <®11>;
|
||||
|
|
|
@ -7,29 +7,23 @@
|
|||
|
||||
/ {
|
||||
aliases {
|
||||
spi0 = &qspi;
|
||||
gpio26 = &stmfx_pinctrl;
|
||||
i2c1 = &i2c2;
|
||||
i2c4 = &i2c5;
|
||||
pinctrl2 = &stmfx_pinctrl;
|
||||
spi0 = &qspi;
|
||||
};
|
||||
};
|
||||
|
||||
&flash0 {
|
||||
compatible = "spi-flash";
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&flash1 {
|
||||
compatible = "spi-flash";
|
||||
};
|
||||
|
||||
&v3v3 {
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
&usbotg_hs {
|
||||
g-tx-fifo-size = <576>;
|
||||
};
|
||||
|
||||
/* SPL part **************************************/
|
||||
&qspi {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
@ -61,7 +55,10 @@
|
|||
};
|
||||
};
|
||||
|
||||
&flash0 {
|
||||
u-boot,dm-spl;
|
||||
&usbotg_hs {
|
||||
g-tx-fifo-size = <576>;
|
||||
};
|
||||
|
||||
&v3v3 {
|
||||
regulator-always-on;
|
||||
};
|
||||
|
|
|
@ -11,6 +11,21 @@
|
|||
model = "STMicroelectronics STM32MP157C eval daughter on eval mother";
|
||||
compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157";
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
aliases {
|
||||
serial0 = &uart4;
|
||||
ethernet0 = ðernet0;
|
||||
};
|
||||
|
||||
panel_backlight: panel-backlight {
|
||||
compatible = "gpio-backlight";
|
||||
gpios = <&gpiod 13 GPIO_ACTIVE_LOW>;
|
||||
default-on;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
&cec {
|
||||
|
@ -19,12 +34,88 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
&dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dsi_in: endpoint {
|
||||
remote-endpoint = <<dc_ep0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
dsi_out: endpoint {
|
||||
remote-endpoint = <&dsi_panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
panel-dsi@0 {
|
||||
compatible = "raydium,rm68200";
|
||||
reg = <0>;
|
||||
reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>;
|
||||
backlight = <&panel_backlight>;
|
||||
status = "okay";
|
||||
|
||||
port {
|
||||
dsi_panel_in: endpoint {
|
||||
remote-endpoint = <&dsi_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ð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@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c2 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c2_pins_a>;
|
||||
i2c-scl-rising-time-ns = <185>;
|
||||
i2c-scl-falling-time-ns = <20>;
|
||||
status = "okay";
|
||||
|
||||
stmfx: stmfx@42 {
|
||||
compatible = "st,stmfx-0300";
|
||||
reg = <0x42>;
|
||||
interrupts = <8 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-parent = <&gpioi>;
|
||||
vdd-supply = <&v3v3>;
|
||||
|
||||
stmfx_pinctrl: stmfx-pin-controller {
|
||||
compatible = "st,stmfx-0300-pinctrl";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
gpio-ranges = <&stmfx_pinctrl 0 0 24>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c5 {
|
||||
|
@ -35,6 +126,26 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
<dc {
|
||||
status = "okay";
|
||||
|
||||
port {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ltdc_ep0_out: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&dsi_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&m_can1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&m_can1_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&qspi {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>;
|
||||
|
@ -60,6 +171,12 @@
|
|||
};
|
||||
};
|
||||
|
||||
&spi1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spi1_pins_a>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&timers2 {
|
||||
status = "disabled";
|
||||
pwm {
|
||||
|
@ -106,6 +223,7 @@
|
|||
&usbotg_hs {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usbotg_hs_pins_a>;
|
||||
dr_mode = "peripheral";
|
||||
phys = <&usbphyc_port1 0>;
|
||||
phy-names = "usb2-phy";
|
||||
status = "okay";
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
};
|
||||
|
||||
psci {
|
||||
compatible = "arm,psci";
|
||||
compatible = "arm,psci-1.0";
|
||||
method = "smc";
|
||||
cpu_off = <0x84000002>;
|
||||
cpu_on = <0x84000003>;
|
||||
|
@ -106,26 +106,6 @@
|
|||
};
|
||||
};
|
||||
|
||||
pm_domain {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "st,stm32mp157c-pd";
|
||||
|
||||
pd_core_ret: core-ret-power-domain@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
#power-domain-cells = <0>;
|
||||
label = "CORE-RETENTION";
|
||||
|
||||
pd_core: core-power-domain@2 {
|
||||
reg = <2>;
|
||||
#power-domain-cells = <0>;
|
||||
label = "CORE";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
|
@ -339,6 +319,34 @@
|
|||
};
|
||||
};
|
||||
|
||||
spi2: spi@4000b000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "st,stm32h7-spi";
|
||||
reg = <0x4000b000 0x400>;
|
||||
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc SPI2_K>;
|
||||
resets = <&rcc SPI2_R>;
|
||||
dmas = <&dmamux1 39 0x400 0x05>,
|
||||
<&dmamux1 40 0x400 0x05>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi3: spi@4000c000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "st,stm32h7-spi";
|
||||
reg = <0x4000c000 0x400>;
|
||||
interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc SPI3_K>;
|
||||
resets = <&rcc SPI3_R>;
|
||||
dmas = <&dmamux1 61 0x400 0x05>,
|
||||
<&dmamux1 62 0x400 0x05>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usart2: serial@4000e000 {
|
||||
compatible = "st,stm32h7-uart";
|
||||
reg = <0x4000e000 0x400>;
|
||||
|
@ -522,6 +530,34 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
spi1: spi@44004000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "st,stm32h7-spi";
|
||||
reg = <0x44004000 0x400>;
|
||||
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc SPI1_K>;
|
||||
resets = <&rcc SPI1_R>;
|
||||
dmas = <&dmamux1 37 0x400 0x05>,
|
||||
<&dmamux1 38 0x400 0x05>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi4: spi@44005000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "st,stm32h7-spi";
|
||||
reg = <0x44005000 0x400>;
|
||||
interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc SPI4_K>;
|
||||
resets = <&rcc SPI4_R>;
|
||||
dmas = <&dmamux1 83 0x400 0x05>,
|
||||
<&dmamux1 84 0x400 0x05>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
timers15: timer@44006000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -584,6 +620,116 @@
|
|||
};
|
||||
};
|
||||
|
||||
spi5: spi@44009000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "st,stm32h7-spi";
|
||||
reg = <0x44009000 0x400>;
|
||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc SPI5_K>;
|
||||
resets = <&rcc SPI5_R>;
|
||||
dmas = <&dmamux1 85 0x400 0x05>,
|
||||
<&dmamux1 86 0x400 0x05>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
dfsdm: dfsdm@4400d000 {
|
||||
compatible = "st,stm32mp1-dfsdm";
|
||||
reg = <0x4400d000 0x800>;
|
||||
clocks = <&rcc DFSDM_K>;
|
||||
clock-names = "dfsdm";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
|
||||
dfsdm0: filter@0 {
|
||||
compatible = "st,stm32-dfsdm-adc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <0>;
|
||||
interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmamux1 101 0x400 0x01>;
|
||||
dma-names = "rx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
dfsdm1: filter@1 {
|
||||
compatible = "st,stm32-dfsdm-adc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <1>;
|
||||
interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmamux1 102 0x400 0x01>;
|
||||
dma-names = "rx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
dfsdm2: filter@2 {
|
||||
compatible = "st,stm32-dfsdm-adc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <2>;
|
||||
interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmamux1 103 0x400 0x01>;
|
||||
dma-names = "rx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
dfsdm3: filter@3 {
|
||||
compatible = "st,stm32-dfsdm-adc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <3>;
|
||||
interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmamux1 104 0x400 0x01>;
|
||||
dma-names = "rx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
dfsdm4: filter@4 {
|
||||
compatible = "st,stm32-dfsdm-adc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <4>;
|
||||
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmamux1 91 0x400 0x01>;
|
||||
dma-names = "rx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
dfsdm5: filter@5 {
|
||||
compatible = "st,stm32-dfsdm-adc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <5>;
|
||||
interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmamux1 92 0x400 0x01>;
|
||||
dma-names = "rx";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
m_can1: can@4400e000 {
|
||||
compatible = "bosch,m_can";
|
||||
reg = <0x4400e000 0x400>, <0x44011000 0x2800>;
|
||||
reg-names = "m_can", "message_ram";
|
||||
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "int0", "int1";
|
||||
clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
|
||||
clock-names = "hclk", "cclk";
|
||||
bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
m_can2: can@4400f000 {
|
||||
compatible = "bosch,m_can";
|
||||
reg = <0x4400f000 0x400>, <0x44011000 0x2800>;
|
||||
reg-names = "m_can", "message_ram";
|
||||
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "int0", "int1";
|
||||
clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
|
||||
clock-names = "hclk", "cclk";
|
||||
bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
dma1: dma@48000000 {
|
||||
compatible = "st,stm32-dma";
|
||||
reg = <0x48000000 0x400>;
|
||||
|
@ -647,6 +793,8 @@
|
|||
reg = <0x0>;
|
||||
interrupt-parent = <&adc>;
|
||||
interrupts = <0>;
|
||||
dmas = <&dmamux1 9 0x400 0x01>;
|
||||
dma-names = "rx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -656,6 +804,8 @@
|
|||
reg = <0x100>;
|
||||
interrupt-parent = <&adc>;
|
||||
interrupts = <1>;
|
||||
dmas = <&dmamux1 10 0x400 0x01>;
|
||||
dma-names = "rx";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
@ -675,7 +825,7 @@
|
|||
};
|
||||
|
||||
usbotg_hs: usb-otg@49000000 {
|
||||
compatible = "st,stm32mp1-hsotg", "snps,dwc2";
|
||||
compatible = "snps,dwc2";
|
||||
reg = <0x49000000 0x10000>;
|
||||
clocks = <&rcc USBO_K>;
|
||||
clock-names = "otg";
|
||||
|
@ -686,7 +836,6 @@
|
|||
g-np-tx-fifo-size = <32>;
|
||||
g-tx-fifo-size = <128 128 64 64 64 64 32 32>;
|
||||
dr_mode = "otg";
|
||||
power-domains = <&pd_core>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -753,8 +902,8 @@
|
|||
reg = <0x5000d000 0x400>;
|
||||
};
|
||||
|
||||
syscfg: system-config@50020000 {
|
||||
compatible = "st,stm32-syscfg", "syscon";
|
||||
syscfg: syscon@50020000 {
|
||||
compatible = "st,stm32mp157-syscfg", "syscon";
|
||||
reg = <0x50020000 0x400>;
|
||||
};
|
||||
|
||||
|
@ -853,6 +1002,18 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
hash1: hash@54002000 {
|
||||
compatible = "st,stm32f756-hash";
|
||||
reg = <0x54002000 0x400>;
|
||||
interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc HASH1>;
|
||||
resets = <&rcc HASH1_R>;
|
||||
dmas = <&mdma1 31 0x10 0x1000A02 0x0 0x0>;
|
||||
dma-names = "in";
|
||||
dma-maxburst = <2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
rng1: rng@54003000 {
|
||||
compatible = "st,stm32-rng";
|
||||
reg = <0x54003000 0x400>;
|
||||
|
@ -871,7 +1032,7 @@
|
|||
dma-requests = <48>;
|
||||
};
|
||||
|
||||
qspi: qspi@58003000 {
|
||||
qspi: spi@58003000 {
|
||||
compatible = "st,stm32f469-qspi";
|
||||
reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
|
||||
reg-names = "qspi", "qspi_mm";
|
||||
|
@ -915,6 +1076,36 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
stmmac_axi_config_0: stmmac-axi-config {
|
||||
snps,wr_osr_lmt = <0x7>;
|
||||
snps,rd_osr_lmt = <0x7>;
|
||||
snps,blen = <0 0 0 0 16 8 4>;
|
||||
};
|
||||
|
||||
ethernet0: ethernet@5800a000 {
|
||||
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";
|
||||
clock-names = "stmmaceth",
|
||||
"mac-clk-tx",
|
||||
"mac-clk-rx",
|
||||
"ethstp",
|
||||
"syscfg-clk";
|
||||
clocks = <&rcc ETHMAC>,
|
||||
<&rcc ETHTX>,
|
||||
<&rcc ETHRX>,
|
||||
<&rcc ETHSTP>,
|
||||
<&rcc SYSCFG>;
|
||||
st,syscon = <&syscfg 0x4>;
|
||||
snps,mixed-burst;
|
||||
snps,pbl = <2>;
|
||||
snps,axi-config = <&stmmac_axi_config_0>;
|
||||
snps,tso;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usbh_ohci: usbh-ohci@5800c000 {
|
||||
compatible = "generic-ohci";
|
||||
reg = <0x5800c000 0x1000>;
|
||||
|
@ -955,6 +1146,14 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
iwdg2: watchdog@5a002000 {
|
||||
compatible = "st,stm32mp1-iwdg";
|
||||
reg = <0x5a002000 0x400>;
|
||||
clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
|
||||
clock-names = "pclk", "lsi";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usbphyc: usbphyc@5a006000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -983,6 +1182,20 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
spi6: spi@5c001000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "st,stm32h7-spi";
|
||||
reg = <0x5c001000 0x400>;
|
||||
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc SPI6_K>;
|
||||
resets = <&rcc SPI6_R>;
|
||||
dmas = <&mdma1 34 0x0 0x40008 0x0 0x0>,
|
||||
<&mdma1 35 0x0 0x40002 0x0 0x0>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c4: i2c@5c002000 {
|
||||
compatible = "st,stm32f7-i2c";
|
||||
reg = <0x5c002000 0x400>;
|
||||
|
@ -996,6 +1209,22 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
rtc: rtc@5c004000 {
|
||||
compatible = "st,stm32mp1-rtc";
|
||||
reg = <0x5c004000 0x400>;
|
||||
clocks = <&rcc RTCAPB>, <&rcc RTC>;
|
||||
clock-names = "pclk", "rtc_ck";
|
||||
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
bsec: nvmem@5c005000 {
|
||||
compatible = "st,stm32mp15-bsec";
|
||||
reg = <0x5c005000 0x400>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
};
|
||||
|
||||
i2c6: i2c@5c009000 {
|
||||
compatible = "st,stm32f7-i2c";
|
||||
reg = <0x5c009000 0x400>;
|
||||
|
|
|
@ -17,7 +17,7 @@ config SPL
|
|||
select SPL_DM_RESET
|
||||
select SPL_SERIAL_SUPPORT
|
||||
select SPL_SYSCON
|
||||
select SPL_DRIVERS_MISC_SUPPORT
|
||||
imply SPL_DISPLAY_PRINT
|
||||
imply SPL_LIBDISK_SUPPORT
|
||||
|
||||
config SYS_SOC
|
||||
|
@ -25,18 +25,31 @@ config SYS_SOC
|
|||
|
||||
config TARGET_STM32MP1
|
||||
bool "Support stm32mp1xx"
|
||||
select ARCH_SUPPORT_PSCI
|
||||
select ARCH_SUPPORT_PSCI if !STM32MP1_TRUSTED
|
||||
select CPU_V7A
|
||||
select CPU_V7_HAS_NONSEC
|
||||
select CPU_V7_HAS_NONSEC if !STM32MP1_TRUSTED
|
||||
select CPU_V7_HAS_VIRT
|
||||
select PINCTRL_STM32
|
||||
select STM32_RCC
|
||||
select STM32_RESET
|
||||
select SYS_ARCH_TIMER
|
||||
select SYSRESET_SYSCON
|
||||
imply SYSRESET_PSCI if STM32MP1_TRUSTED
|
||||
imply SYSRESET_SYSCON if !STM32MP1_TRUSTED
|
||||
help
|
||||
target STMicroelectronics SOC STM32MP1 family
|
||||
STM32MP157, STM32MP153 or STM32MP151
|
||||
STMicroelectronics MPU with core ARMv7
|
||||
dual core A7 for STM32MP157/3, monocore for STM32MP151
|
||||
|
||||
config STM32MP1_TRUSTED
|
||||
bool "Support trusted boot with TF-A"
|
||||
default y if !SPL
|
||||
select ARM_SMCCC
|
||||
help
|
||||
Say Y here to enable boot with TF-A
|
||||
Trusted boot chain is :
|
||||
BootRom => TF-A.stm32 (clock & DDR) => U-Boot.stm32
|
||||
TF-A monitor provides proprietary smc to manage secure devices
|
||||
|
||||
config SYS_TEXT_BASE
|
||||
prompt "U-Boot base address"
|
||||
|
@ -46,6 +59,9 @@ config SYS_TEXT_BASE
|
|||
when DDR driver is used:
|
||||
DDR + 1MB (0xC0100000)
|
||||
|
||||
config NR_DRAM_BANKS
|
||||
default 1
|
||||
|
||||
config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2
|
||||
hex "Partition on MMC2 to use to load U-Boot from"
|
||||
depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
|
||||
|
@ -54,9 +70,6 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2
|
|||
Partition on the second MMC to load U-Boot from when the MMC is being
|
||||
used in raw mode
|
||||
|
||||
source "board/st/stm32mp1/Kconfig"
|
||||
|
||||
# currently activated for debug / should be deactivated for real product
|
||||
if DEBUG_UART
|
||||
|
||||
config DEBUG_UART_BOARD_INIT
|
||||
|
@ -71,4 +84,6 @@ config DEBUG_UART_CLOCK
|
|||
default 64000000
|
||||
endif
|
||||
|
||||
source "board/st/stm32mp1/Kconfig"
|
||||
|
||||
endif
|
||||
|
|
|
@ -11,6 +11,9 @@ ifdef CONFIG_SPL_BUILD
|
|||
obj-y += spl.o
|
||||
else
|
||||
obj-y += bsec.o
|
||||
ifndef CONFIG_STM32MP1_TRUSTED
|
||||
obj-$(CONFIG_SYSRESET) += cmd_poweroff.o
|
||||
endif
|
||||
endif
|
||||
obj-$(CONFIG_ARMV7_PSCI) += psci.o
|
||||
obj-$(CONFIG_$(SPL_)DM_REGULATOR) += pwr_regulator.o
|
||||
|
|
|
@ -8,9 +8,12 @@
|
|||
#include <misc.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <asm/arch/stm32mp1_smc.h>
|
||||
#include <linux/arm-smccc.h>
|
||||
|
||||
#define BSEC_OTP_MAX_VALUE 95
|
||||
|
||||
#ifndef CONFIG_STM32MP1_TRUSTED
|
||||
#define BSEC_TIMEOUT_US 10000
|
||||
|
||||
/* BSEC REGISTER OFFSET (base relative) */
|
||||
|
@ -168,7 +171,7 @@ static int bsec_shadow_register(u32 base, u32 otp)
|
|||
ret = bsec_power_safmem(base, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
power_up = 1;
|
||||
power_up = true;
|
||||
}
|
||||
/* set BSEC_OTP_CTRL_OFF with the otp value*/
|
||||
writel(otp | BSEC_READ, base + BSEC_OTP_CTRL_OFF);
|
||||
|
@ -270,6 +273,7 @@ static int bsec_program_otp(long base, u32 val, u32 otp)
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_STM32MP1_TRUSTED */
|
||||
|
||||
/* BSEC MISC driver *******************************************************/
|
||||
struct stm32mp_bsec_platdata {
|
||||
|
@ -278,6 +282,11 @@ struct stm32mp_bsec_platdata {
|
|||
|
||||
static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
|
||||
{
|
||||
#ifdef CONFIG_STM32MP1_TRUSTED
|
||||
return stm32_smc(STM32_SMC_BSEC,
|
||||
STM32_SMC_READ_OTP,
|
||||
otp, 0, val);
|
||||
#else
|
||||
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
|
||||
u32 tmp_data = 0;
|
||||
int ret;
|
||||
|
@ -299,27 +308,46 @@ static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
|
|||
/* restore shadow value */
|
||||
ret = bsec_write_shadow(plat->base, tmp_data, otp);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
|
||||
{
|
||||
#ifdef CONFIG_STM32MP1_TRUSTED
|
||||
return stm32_smc(STM32_SMC_BSEC,
|
||||
STM32_SMC_READ_SHADOW,
|
||||
otp, 0, val);
|
||||
#else
|
||||
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
|
||||
|
||||
return bsec_read_shadow(plat->base, val, otp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
|
||||
{
|
||||
#ifdef CONFIG_STM32MP1_TRUSTED
|
||||
return stm32_smc_exec(STM32_SMC_BSEC,
|
||||
STM32_SMC_PROG_OTP,
|
||||
otp, val);
|
||||
#else
|
||||
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
|
||||
|
||||
return bsec_program_otp(plat->base, val, otp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
|
||||
{
|
||||
#ifdef CONFIG_STM32MP1_TRUSTED
|
||||
return stm32_smc_exec(STM32_SMC_BSEC,
|
||||
STM32_SMC_WRITE_SHADOW,
|
||||
otp, val);
|
||||
#else
|
||||
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
|
||||
|
||||
return bsec_write_shadow(plat->base, val, otp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int stm32mp_bsec_read(struct udevice *dev, int offset,
|
||||
|
@ -405,8 +433,23 @@ static int stm32mp_bsec_ofdata_to_platdata(struct udevice *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_STM32MP1_TRUSTED
|
||||
static int stm32mp_bsec_probe(struct udevice *dev)
|
||||
{
|
||||
int otp;
|
||||
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
|
||||
|
||||
/* update unlocked shadow for OTP cleared by the rom code */
|
||||
for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++)
|
||||
if (!bsec_read_SR_lock(plat->base, otp))
|
||||
bsec_shadow_register(plat->base, otp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct udevice_id stm32mp_bsec_ids[] = {
|
||||
{ .compatible = "st,stm32mp-bsec" },
|
||||
{ .compatible = "st,stm32mp15-bsec" },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -417,14 +460,7 @@ U_BOOT_DRIVER(stm32mp_bsec) = {
|
|||
.ofdata_to_platdata = stm32mp_bsec_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct stm32mp_bsec_platdata),
|
||||
.ops = &stm32mp_bsec_ops,
|
||||
};
|
||||
|
||||
/* bsec IP is not present in device tee, manage IP address by platdata */
|
||||
static struct stm32mp_bsec_platdata stm32_bsec_platdata = {
|
||||
.base = STM32_BSEC_BASE,
|
||||
};
|
||||
|
||||
U_BOOT_DEVICE(stm32mp_bsec) = {
|
||||
.name = "stm32mp_bsec",
|
||||
.platdata = &stm32_bsec_platdata,
|
||||
#ifndef CONFIG_STM32MP1_TRUSTED
|
||||
.probe = stm32mp_bsec_probe,
|
||||
#endif
|
||||
};
|
||||
|
|
24
arch/arm/mach-stm32mp/cmd_poweroff.c
Normal file
24
arch/arm/mach-stm32mp/cmd_poweroff.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2019, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <sysreset.h>
|
||||
|
||||
int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
puts("poweroff ...\n");
|
||||
mdelay(100);
|
||||
|
||||
ret = sysreset_walk(SYSRESET_POWER);
|
||||
|
||||
if (ret == -EINPROGRESS)
|
||||
mdelay(1000);
|
||||
|
||||
/*NOTREACHED when power off*/
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
|
@ -3,7 +3,20 @@
|
|||
# Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
||||
#
|
||||
|
||||
ALL-$(CONFIG_SPL_BUILD) += u-boot-spl.stm32
|
||||
ifndef CONFIG_SPL
|
||||
ALL-y += u-boot.stm32
|
||||
else
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
ALL-y += u-boot-spl.stm32
|
||||
endif
|
||||
endif
|
||||
|
||||
MKIMAGEFLAGS_u-boot.stm32 = -T stm32image -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE)
|
||||
|
||||
u-boot.stm32: MKIMAGEOUTPUT = u-boot.stm32.log
|
||||
|
||||
u-boot.stm32: u-boot.bin FORCE
|
||||
$(call if_changed,mkimage)
|
||||
|
||||
MKIMAGEFLAGS_u-boot-spl.stm32 = -T stm32image -a $(CONFIG_SPL_TEXT_BASE) -e $(CONFIG_SPL_TEXT_BASE)
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#define RCC_DBGCFGR (STM32_RCC_BASE + 0x080C)
|
||||
#define RCC_BDCR (STM32_RCC_BASE + 0x0140)
|
||||
#define RCC_MP_APB5ENSETR (STM32_RCC_BASE + 0x0208)
|
||||
#define RCC_MP_AHB5ENSETR (STM32_RCC_BASE + 0x0210)
|
||||
#define RCC_BDCR_VSWRST BIT(31)
|
||||
#define RCC_BDCR_RTCSRC GENMASK(17, 16)
|
||||
#define RCC_DBGCFGR_DBGCKEN BIT(8)
|
||||
|
@ -44,6 +45,9 @@
|
|||
#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16)
|
||||
#define DBGMCU_IDC_REV_ID_SHIFT 16
|
||||
|
||||
/* GPIOZ registers */
|
||||
#define GPIOZ_SECCFGR 0x54004030
|
||||
|
||||
/* boot interface from Bootrom
|
||||
* - boot instance = bit 31:16
|
||||
* - boot device = bit 15:0
|
||||
|
@ -55,10 +59,32 @@
|
|||
#define BOOTROM_INSTANCE_SHIFT 16
|
||||
|
||||
/* BSEC OTP index */
|
||||
#define BSEC_OTP_RPN 1
|
||||
#define BSEC_OTP_SERIAL 13
|
||||
#define BSEC_OTP_PKG 16
|
||||
#define BSEC_OTP_MAC 57
|
||||
|
||||
/* Device Part Number (RPN) = OTP_DATA1 lower 8 bits */
|
||||
#define RPN_SHIFT 0
|
||||
#define RPN_MASK GENMASK(7, 0)
|
||||
|
||||
/* Package = bit 27:29 of OTP16
|
||||
* - 100: LBGA448 (FFI) => AA = LFBGA 18x18mm 448 balls p. 0.8mm
|
||||
* - 011: LBGA354 (LCI) => AB = LFBGA 16x16mm 359 balls p. 0.8mm
|
||||
* - 010: TFBGA361 (FFC) => AC = TFBGA 12x12mm 361 balls p. 0.5mm
|
||||
* - 001: TFBGA257 (LCC) => AD = TFBGA 10x10mm 257 balls p. 0.5mm
|
||||
* - others: Reserved
|
||||
*/
|
||||
#define PKG_SHIFT 27
|
||||
#define PKG_MASK GENMASK(2, 0)
|
||||
|
||||
#define PKG_AA_LBGA448 4
|
||||
#define PKG_AB_LBGA354 3
|
||||
#define PKG_AC_TFBGA361 2
|
||||
#define PKG_AD_TFBGA257 1
|
||||
|
||||
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
|
||||
#ifndef CONFIG_STM32MP1_TRUSTED
|
||||
static void security_init(void)
|
||||
{
|
||||
/* Disable the backup domain write protection */
|
||||
|
@ -113,7 +139,12 @@ static void security_init(void)
|
|||
* Bit 16 ITAMP1E: RTC power domain supply monitoring
|
||||
*/
|
||||
writel(0x0, TAMP_CR1);
|
||||
|
||||
/* GPIOZ: deactivate the security */
|
||||
writel(BIT(0), RCC_MP_AHB5ENSETR);
|
||||
writel(0x0, GPIOZ_SECCFGR);
|
||||
}
|
||||
#endif /* CONFIG_STM32MP1_TRUSTED */
|
||||
|
||||
/*
|
||||
* Debug init
|
||||
|
@ -127,13 +158,19 @@ static void dbgmcu_init(void)
|
|||
}
|
||||
#endif /* !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) */
|
||||
|
||||
static u32 get_bootmode(void)
|
||||
#if !defined(CONFIG_STM32MP1_TRUSTED) && \
|
||||
(!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
|
||||
/* get bootmode from ROM code boot context: saved in TAMP register */
|
||||
static void update_bootmode(void)
|
||||
{
|
||||
u32 boot_mode;
|
||||
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
|
||||
u32 bootrom_itf = readl(BOOTROM_PARAM_ADDR);
|
||||
u32 bootrom_device, bootrom_instance;
|
||||
|
||||
/* enable TAMP clock = RTCAPBEN */
|
||||
writel(BIT(8), RCC_MP_APB5ENSETR);
|
||||
|
||||
/* read bootrom context */
|
||||
bootrom_device =
|
||||
(bootrom_itf & BOOTROM_MODE_MASK) >> BOOTROM_MODE_SHIFT;
|
||||
bootrom_instance =
|
||||
|
@ -147,12 +184,14 @@ static u32 get_bootmode(void)
|
|||
clrsetbits_le32(TAMP_BOOT_CONTEXT,
|
||||
TAMP_BOOT_MODE_MASK,
|
||||
boot_mode << TAMP_BOOT_MODE_SHIFT);
|
||||
#else
|
||||
/* read TAMP backup register */
|
||||
boot_mode = (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >>
|
||||
TAMP_BOOT_MODE_SHIFT;
|
||||
}
|
||||
#endif
|
||||
return boot_mode;
|
||||
|
||||
u32 get_bootmode(void)
|
||||
{
|
||||
/* read bootmode from TAMP backup register */
|
||||
return (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >>
|
||||
TAMP_BOOT_MODE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -167,16 +206,18 @@ int arch_cpu_init(void)
|
|||
|
||||
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
|
||||
dbgmcu_init();
|
||||
|
||||
#ifndef CONFIG_STM32MP1_TRUSTED
|
||||
security_init();
|
||||
update_bootmode();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* get bootmode from BootRom context: saved in TAMP register */
|
||||
boot_mode = get_bootmode();
|
||||
|
||||
if ((boot_mode & TAMP_BOOT_DEVICE_MASK) == BOOT_SERIAL_UART)
|
||||
gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE;
|
||||
#if defined(CONFIG_DEBUG_UART) && \
|
||||
!defined(CONFIG_STM32MP1_TRUSTED) && \
|
||||
(!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
|
||||
else
|
||||
debug_uart_init();
|
||||
|
@ -203,25 +244,94 @@ u32 get_cpu_rev(void)
|
|||
return (read_idc() & DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
|
||||
}
|
||||
|
||||
static u32 get_otp(int index, int shift, int mask)
|
||||
{
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
u32 otp = 0;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_MISC,
|
||||
DM_GET_DRIVER(stm32mp_bsec),
|
||||
&dev);
|
||||
|
||||
if (!ret)
|
||||
ret = misc_read(dev, STM32_BSEC_SHADOW(index),
|
||||
&otp, sizeof(otp));
|
||||
|
||||
return (otp >> shift) & mask;
|
||||
}
|
||||
|
||||
/* Get Device Part Number (RPN) from OTP */
|
||||
static u32 get_cpu_rpn(void)
|
||||
{
|
||||
return get_otp(BSEC_OTP_RPN, RPN_SHIFT, RPN_MASK);
|
||||
}
|
||||
|
||||
u32 get_cpu_type(void)
|
||||
{
|
||||
return (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT;
|
||||
u32 id;
|
||||
|
||||
id = (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT;
|
||||
|
||||
return (id << 16) | get_cpu_rpn();
|
||||
}
|
||||
|
||||
/* Get Package options from OTP */
|
||||
static u32 get_cpu_package(void)
|
||||
{
|
||||
return get_otp(BSEC_OTP_PKG, PKG_SHIFT, PKG_MASK);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DISPLAY_CPUINFO)
|
||||
int print_cpuinfo(void)
|
||||
{
|
||||
char *cpu_s, *cpu_r;
|
||||
char *cpu_s, *cpu_r, *pkg;
|
||||
|
||||
/* MPUs Part Numbers */
|
||||
switch (get_cpu_type()) {
|
||||
case CPU_STMP32MP15x:
|
||||
cpu_s = "15x";
|
||||
case CPU_STM32MP157Cxx:
|
||||
cpu_s = "157C";
|
||||
break;
|
||||
case CPU_STM32MP157Axx:
|
||||
cpu_s = "157A";
|
||||
break;
|
||||
case CPU_STM32MP153Cxx:
|
||||
cpu_s = "153C";
|
||||
break;
|
||||
case CPU_STM32MP153Axx:
|
||||
cpu_s = "153A";
|
||||
break;
|
||||
case CPU_STM32MP151Cxx:
|
||||
cpu_s = "151C";
|
||||
break;
|
||||
case CPU_STM32MP151Axx:
|
||||
cpu_s = "151A";
|
||||
break;
|
||||
default:
|
||||
cpu_s = "?";
|
||||
cpu_s = "????";
|
||||
break;
|
||||
}
|
||||
|
||||
/* Package */
|
||||
switch (get_cpu_package()) {
|
||||
case PKG_AA_LBGA448:
|
||||
pkg = "AA";
|
||||
break;
|
||||
case PKG_AB_LBGA354:
|
||||
pkg = "AB";
|
||||
break;
|
||||
case PKG_AC_TFBGA361:
|
||||
pkg = "AC";
|
||||
break;
|
||||
case PKG_AD_TFBGA257:
|
||||
pkg = "AD";
|
||||
break;
|
||||
default:
|
||||
pkg = "??";
|
||||
break;
|
||||
}
|
||||
|
||||
/* REVISION */
|
||||
switch (get_cpu_rev()) {
|
||||
case CPU_REVA:
|
||||
cpu_r = "A";
|
||||
|
@ -234,7 +344,7 @@ int print_cpuinfo(void)
|
|||
break;
|
||||
}
|
||||
|
||||
printf("CPU: STM32MP%s.%s\n", cpu_s, cpu_r);
|
||||
printf("CPU: STM32MP%s%s Rev.%s\n", cpu_s, pkg, cpu_r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -242,20 +352,48 @@ int print_cpuinfo(void)
|
|||
|
||||
static void setup_boot_mode(void)
|
||||
{
|
||||
const u32 serial_addr[] = {
|
||||
STM32_USART1_BASE,
|
||||
STM32_USART2_BASE,
|
||||
STM32_USART3_BASE,
|
||||
STM32_UART4_BASE,
|
||||
STM32_UART5_BASE,
|
||||
STM32_USART6_BASE,
|
||||
STM32_UART7_BASE,
|
||||
STM32_UART8_BASE
|
||||
};
|
||||
char cmd[60];
|
||||
u32 boot_ctx = readl(TAMP_BOOT_CONTEXT);
|
||||
u32 boot_mode =
|
||||
(boot_ctx & TAMP_BOOT_MODE_MASK) >> TAMP_BOOT_MODE_SHIFT;
|
||||
int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1;
|
||||
u32 forced_mode = (boot_ctx & TAMP_BOOT_FORCED_MASK);
|
||||
struct udevice *dev;
|
||||
int alias;
|
||||
|
||||
pr_debug("%s: boot_ctx=0x%x => boot_mode=%x, instance=%d\n",
|
||||
__func__, boot_ctx, boot_mode, instance);
|
||||
|
||||
pr_debug("%s: boot_ctx=0x%x => boot_mode=%x, instance=%d forced=%x\n",
|
||||
__func__, boot_ctx, boot_mode, instance, forced_mode);
|
||||
switch (boot_mode & TAMP_BOOT_DEVICE_MASK) {
|
||||
case BOOT_SERIAL_UART:
|
||||
sprintf(cmd, "%d", instance);
|
||||
env_set("boot_device", "uart");
|
||||
if (instance > ARRAY_SIZE(serial_addr))
|
||||
break;
|
||||
/* serial : search associated alias in devicetree */
|
||||
sprintf(cmd, "serial@%x", serial_addr[instance]);
|
||||
if (uclass_get_device_by_name(UCLASS_SERIAL, cmd, &dev))
|
||||
break;
|
||||
if (fdtdec_get_alias_seq(gd->fdt_blob, "serial",
|
||||
dev_of_offset(dev), &alias))
|
||||
break;
|
||||
sprintf(cmd, "%d", alias);
|
||||
env_set("boot_device", "serial");
|
||||
env_set("boot_instance", cmd);
|
||||
|
||||
/* restore console on uart when not used */
|
||||
if (gd->cur_serial_dev != dev) {
|
||||
gd->flags &= ~(GD_FLG_SILENT |
|
||||
GD_FLG_DISABLE_CONSOLE);
|
||||
printf("serial boot with console enabled!\n");
|
||||
}
|
||||
break;
|
||||
case BOOT_SERIAL_USB:
|
||||
env_set("boot_device", "usb");
|
||||
|
@ -279,6 +417,36 @@ static void setup_boot_mode(void)
|
|||
pr_debug("unexpected boot mode = %x\n", boot_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (forced_mode) {
|
||||
case BOOT_FASTBOOT:
|
||||
printf("Enter fastboot!\n");
|
||||
env_set("preboot", "env set preboot; fastboot 0");
|
||||
break;
|
||||
case BOOT_STM32PROG:
|
||||
env_set("boot_device", "usb");
|
||||
env_set("boot_instance", "0");
|
||||
break;
|
||||
case BOOT_UMS_MMC0:
|
||||
case BOOT_UMS_MMC1:
|
||||
case BOOT_UMS_MMC2:
|
||||
printf("Enter UMS!\n");
|
||||
instance = forced_mode - BOOT_UMS_MMC0;
|
||||
sprintf(cmd, "env set preboot; ums 0 mmc %d", instance);
|
||||
env_set("preboot", cmd);
|
||||
break;
|
||||
case BOOT_RECOVERY:
|
||||
env_set("preboot", "env set preboot; run altbootcmd");
|
||||
break;
|
||||
case BOOT_NORMAL:
|
||||
break;
|
||||
default:
|
||||
pr_debug("unexpected forced boot mode = %x\n", forced_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
/* clear TAMP for next reboot */
|
||||
clrsetbits_le32(TAMP_BOOT_CONTEXT, TAMP_BOOT_FORCED_MASK, BOOT_NORMAL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -304,7 +472,7 @@ static int setup_mac_address(void)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = misc_read(dev, BSEC_OTP_MAC * 4 + STM32_BSEC_OTP_OFFSET,
|
||||
ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_MAC),
|
||||
otp, sizeof(otp));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -342,12 +510,12 @@ static int setup_serial_number(void)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = misc_read(dev, BSEC_OTP_SERIAL * 4 + STM32_BSEC_OTP_OFFSET,
|
||||
ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_SERIAL),
|
||||
otp, sizeof(otp));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
sprintf(serial_string, "%08x%08x%08x", otp[0], otp[1], otp[2]);
|
||||
sprintf(serial_string, "%08X%08X%08X", otp[0], otp[1], otp[2]);
|
||||
env_set("serial#", serial_string);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -13,13 +13,10 @@
|
|||
#define STM32_RCC_BASE 0x50000000
|
||||
#define STM32_PWR_BASE 0x50001000
|
||||
#define STM32_DBGMCU_BASE 0x50081000
|
||||
#define STM32_BSEC_BASE 0x5C005000
|
||||
#define STM32_TZC_BASE 0x5C006000
|
||||
#define STM32_ETZPC_BASE 0x5C007000
|
||||
#define STM32_TAMP_BASE 0x5C00A000
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_BASE
|
||||
/* hardcoded value can be only used for DEBUG UART */
|
||||
#define STM32_USART1_BASE 0x5C000000
|
||||
#define STM32_USART2_BASE 0x4000E000
|
||||
#define STM32_USART3_BASE 0x4000F000
|
||||
|
@ -28,7 +25,6 @@
|
|||
#define STM32_USART6_BASE 0x44003000
|
||||
#define STM32_UART7_BASE 0x40018000
|
||||
#define STM32_UART8_BASE 0x40019000
|
||||
#endif
|
||||
|
||||
#define STM32_SYSRAM_BASE 0x2FFC0000
|
||||
#define STM32_SYSRAM_SIZE SZ_256K
|
||||
|
@ -40,8 +36,10 @@
|
|||
/* enumerated used to identify the SYSCON driver instance */
|
||||
enum {
|
||||
STM32MP_SYSCON_UNKNOWN,
|
||||
STM32MP_SYSCON_STGEN,
|
||||
STM32MP_SYSCON_ETZPC,
|
||||
STM32MP_SYSCON_PWR,
|
||||
STM32MP_SYSCON_STGEN,
|
||||
STM32MP_SYSCON_SYSCFG,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -95,10 +93,25 @@ enum boot_device {
|
|||
#define TAMP_BOOT_MODE_SHIFT 8
|
||||
#define TAMP_BOOT_DEVICE_MASK GENMASK(7, 4)
|
||||
#define TAMP_BOOT_INSTANCE_MASK GENMASK(3, 0)
|
||||
#define TAMP_BOOT_FORCED_MASK GENMASK(7, 0)
|
||||
|
||||
enum forced_boot_mode {
|
||||
BOOT_NORMAL = 0x00,
|
||||
BOOT_FASTBOOT = 0x01,
|
||||
BOOT_RECOVERY = 0x02,
|
||||
BOOT_STM32PROG = 0x03,
|
||||
BOOT_UMS_MMC0 = 0x10,
|
||||
BOOT_UMS_MMC1 = 0x11,
|
||||
BOOT_UMS_MMC2 = 0x12,
|
||||
};
|
||||
|
||||
/* offset used for BSEC driver: misc_read and misc_write */
|
||||
#define STM32_BSEC_SHADOW_OFFSET 0x0
|
||||
#define STM32_BSEC_SHADOW(id) (STM32_BSEC_SHADOW_OFFSET + (id) * 4)
|
||||
#define STM32_BSEC_OTP_OFFSET 0x80000000
|
||||
#define STM32_BSEC_OTP(id) (STM32_BSEC_OTP_OFFSET + (id) * 4)
|
||||
|
||||
#define BSEC_OTP_BOARD 59
|
||||
|
||||
#endif /* __ASSEMBLY__*/
|
||||
#endif /* _MACH_STM32_H_ */
|
||||
|
|
64
arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
Normal file
64
arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2019, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
#ifndef __STM32MP1_SMC_H__
|
||||
#define __STM32MP1_SMC_H__
|
||||
|
||||
#include <linux/arm-smccc.h>
|
||||
|
||||
/*
|
||||
* SMC function IDs for STM32 Service queries
|
||||
* STM32 SMC services use the space between 0x82000000 and 0x8200FFFF
|
||||
* like this is defined in SMC calling Convention by ARM
|
||||
* for SiP (silicon Partner)
|
||||
* http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
|
||||
*/
|
||||
#define STM32_SMC_VERSION 0x82000000
|
||||
|
||||
/* Secure Service access from Non-secure */
|
||||
#define STM32_SMC_BSEC 0x82001003
|
||||
|
||||
/* Service for BSEC */
|
||||
#define STM32_SMC_READ_SHADOW 0x01
|
||||
#define STM32_SMC_PROG_OTP 0x02
|
||||
#define STM32_SMC_WRITE_SHADOW 0x03
|
||||
#define STM32_SMC_READ_OTP 0x04
|
||||
#define STM32_SMC_READ_ALL 0x05
|
||||
#define STM32_SMC_WRITE_ALL 0x06
|
||||
|
||||
/* SMC error codes */
|
||||
#define STM32_SMC_OK 0x0
|
||||
#define STM32_SMC_NOT_SUPPORTED -1
|
||||
#define STM32_SMC_FAILED -2
|
||||
#define STM32_SMC_INVALID_PARAMS -3
|
||||
|
||||
#define stm32_smc_exec(svc, op, data1, data2) \
|
||||
stm32_smc(svc, op, data1, data2, NULL)
|
||||
|
||||
#ifdef CONFIG_ARM_SMCCC
|
||||
static inline u32 stm32_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *result)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
arm_smccc_smc(svc, op, data1, data2, 0, 0, 0, 0, &res);
|
||||
|
||||
if (res.a0) {
|
||||
pr_err("%s: Failed to exec in secure mode (err = %ld)\n",
|
||||
__func__, res.a0);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (result)
|
||||
*result = (u32)res.a1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline u32 stm32_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *result)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32MP1_SMC_H__ */
|
|
@ -3,9 +3,15 @@
|
|||
* Copyright (C) 2015-2017, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
#define CPU_STMP32MP15x 0x500
|
||||
/* ID = Device Version (bit31:16) + Device Part Number (RPN) (bit15:0)*/
|
||||
#define CPU_STM32MP157Cxx 0x05000000
|
||||
#define CPU_STM32MP157Axx 0x05000001
|
||||
#define CPU_STM32MP153Cxx 0x05000024
|
||||
#define CPU_STM32MP153Axx 0x05000025
|
||||
#define CPU_STM32MP151Cxx 0x0500002E
|
||||
#define CPU_STM32MP151Axx 0x0500002F
|
||||
|
||||
/* return CPU_STMP32MPxx constants */
|
||||
/* return CPU_STMP32MP...Xxx constants */
|
||||
u32 get_cpu_type(void);
|
||||
|
||||
#define CPU_REVA 0x1000
|
||||
|
@ -13,3 +19,5 @@ u32 get_cpu_type(void);
|
|||
|
||||
/* return CPU_REV constants */
|
||||
u32 get_cpu_rev(void);
|
||||
/* return boot mode */
|
||||
u32 get_bootmode(void);
|
||||
|
|
|
@ -103,7 +103,13 @@ int __secure psci_affinity_info(u32 function_id, u32 target_affinity,
|
|||
|
||||
int __secure psci_migrate_info_type(u32 function_id)
|
||||
{
|
||||
/* Trusted OS is either not present or does not require migration */
|
||||
/*
|
||||
* in Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
|
||||
* return 2 = Trusted OS is either not present or does not require
|
||||
* migration, system of this type does not require the caller
|
||||
* to use the MIGRATE function.
|
||||
* MIGRATE function calls return NOT_SUPPORTED.
|
||||
*/
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
#include <dm.h>
|
||||
#include <spl.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <linux/libfdt.h>
|
||||
|
||||
u32 spl_boot_device(void)
|
||||
{
|
||||
u32 boot_mode;
|
||||
|
||||
boot_mode = (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >>
|
||||
TAMP_BOOT_MODE_SHIFT;
|
||||
boot_mode = get_bootmode();
|
||||
|
||||
switch (boot_mode) {
|
||||
case BOOT_FLASH_SD_1:
|
||||
|
@ -22,6 +23,21 @@ u32 spl_boot_device(void)
|
|||
case BOOT_FLASH_SD_2:
|
||||
case BOOT_FLASH_EMMC_2:
|
||||
return BOOT_DEVICE_MMC2;
|
||||
case BOOT_SERIAL_UART_1:
|
||||
case BOOT_SERIAL_UART_2:
|
||||
case BOOT_SERIAL_UART_3:
|
||||
case BOOT_SERIAL_UART_4:
|
||||
case BOOT_SERIAL_UART_5:
|
||||
case BOOT_SERIAL_UART_6:
|
||||
case BOOT_SERIAL_UART_7:
|
||||
case BOOT_SERIAL_UART_8:
|
||||
return BOOT_DEVICE_UART;
|
||||
case BOOT_SERIAL_USB_OTG:
|
||||
return BOOT_DEVICE_USB;
|
||||
case BOOT_FLASH_NAND_FMC:
|
||||
return BOOT_DEVICE_NAND;
|
||||
case BOOT_FLASH_NOR_QSPI:
|
||||
return BOOT_DEVICE_SPI;
|
||||
}
|
||||
|
||||
return BOOT_DEVICE_MMC1;
|
||||
|
@ -44,6 +60,21 @@ int spl_boot_partition(const u32 boot_device)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPL_DISPLAY_PRINT
|
||||
void spl_display_print(void)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
const char *model;
|
||||
|
||||
/* same code than show_board_info() but not compiled for SPL
|
||||
* see CONFIG_DISPLAY_BOARDINFO & common/board_info.c
|
||||
*/
|
||||
model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
|
||||
if (model)
|
||||
printf("Model: %s\n", model);
|
||||
}
|
||||
#endif
|
||||
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
struct udevice *dev;
|
||||
|
@ -80,7 +111,7 @@ void board_init_f(ulong dummy)
|
|||
|
||||
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
|
||||
if (ret) {
|
||||
debug("DRAM init failed: %d\n", ret);
|
||||
return;
|
||||
printf("DRAM init failed: %d\n", ret);
|
||||
hang();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,10 +9,11 @@
|
|||
#include <asm/arch/stm32.h>
|
||||
|
||||
static const struct udevice_id stm32mp_syscon_ids[] = {
|
||||
{ .compatible = "st,stm32-stgen",
|
||||
.data = STM32MP_SYSCON_STGEN },
|
||||
{ .compatible = "st,stm32mp1-pwr",
|
||||
.data = STM32MP_SYSCON_PWR },
|
||||
{ .compatible = "st,stm32mp1-etzpc", .data = STM32MP_SYSCON_ETZPC },
|
||||
{ .compatible = "st,stm32mp1-pwr", .data = STM32MP_SYSCON_PWR },
|
||||
{ .compatible = "st,stm32-stgen", .data = STM32MP_SYSCON_STGEN },
|
||||
{ .compatible = "st,stm32mp157-syscfg",
|
||||
.data = STM32MP_SYSCON_SYSCFG },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@ STM32MP1 BOARD
|
|||
M: Patrick Delaunay <patrick.delaunay@st.com>
|
||||
L: uboot-stm32@st-md-mailman.stormreply.com (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: board/st/stm32mp1
|
||||
F: include/configs/stm32mp1.h
|
||||
F: configs/stm32mp15_basic_defconfig
|
||||
F: arch/arm/dts/stm32mp157*
|
||||
F: board/st/stm32mp1
|
||||
F: configs/stm32mp15_basic_defconfig
|
||||
F: configs/stm32mp15_trusted_defconfig
|
||||
F: include/configs/stm32mp1.h
|
||||
|
|
|
@ -28,14 +28,15 @@ Everything is supported in Linux but U-Boot is limited to:
|
|||
|
||||
And the necessary drivers
|
||||
1. I2C
|
||||
2. STPMU1
|
||||
2. STPMU1 (PMIC and regulator)
|
||||
2. STPMIC1 (PMIC and regulator)
|
||||
3. Clock, Reset, Sysreset
|
||||
4. Fuse
|
||||
|
||||
Currently the following boards are supported:
|
||||
+ stm32mp157c-ev1
|
||||
+ stm32mp157c-ed1
|
||||
+ stm32mp157a-dk1
|
||||
+ stm32mp157c-dk2
|
||||
|
||||
3. Boot Sequences
|
||||
=================
|
||||
|
@ -45,15 +46,22 @@ BootRom => FSBL in SYSRAM => SSBL in DDR => OS (Linux Kernel)
|
|||
with FSBL = First Stage Bootloader
|
||||
SSBL = Second Stage Bootloader
|
||||
|
||||
One boot configuration is supported:
|
||||
2 boot configurations are supported:
|
||||
|
||||
The "Basic" boot chain (defconfig_file : stm32mp15_basic_defconfig)
|
||||
1) The "Trusted" boot chain (defconfig_file : stm32mp15_trusted_defconfig)
|
||||
BootRom => FSBL = Trusted Firmware-A (TF-A) => SSBL = U-Boot
|
||||
TF-A performs a full initialization of Secure peripherals and installs a
|
||||
secure monitor.
|
||||
U-Boot is running in normal world and uses TF-A monitor
|
||||
to access to secure resources
|
||||
|
||||
2) The "Basic" boot chain (defconfig_file : stm32mp15_basic_defconfig)
|
||||
BootRom => FSBL = U-Boot SPL => SSBL = U-Boot
|
||||
SPL has limited security initialisation
|
||||
U-Boot is running in secure mode and provide a secure monitor to the kernel
|
||||
with only PSCI support (Power State Coordination Interface defined by ARM)
|
||||
|
||||
All the STM32MP1 board supported by U-Boot use the same generic board
|
||||
All the STM32MP1 boards supported by U-Boot use the same generic board
|
||||
stm32mp1 which support all the bootable devices.
|
||||
|
||||
Each board is configurated only with the associated device tree.
|
||||
|
@ -64,12 +72,18 @@ Each board is configurated only with the associated device tree.
|
|||
You need to select the appropriate device tree for your board,
|
||||
the supported device trees for stm32mp157 are:
|
||||
|
||||
+ ev1: eval board with pmic stpmu1 (ev1 = mother board + daughter ed1)
|
||||
+ ev1: eval board with pmic stpmic1 (ev1 = mother board + daughter ed1)
|
||||
dts: stm32mp157c-ev1
|
||||
|
||||
+ ed1: daughter board with pmic stpmu1
|
||||
+ ed1: daughter board with pmic stpmic1
|
||||
dts: stm32mp157c-ed1
|
||||
|
||||
+ dk1: Discovery board
|
||||
dts: stm32mp157a-dk1
|
||||
|
||||
+ dk2: Discovery board = dk1 with a BT/WiFI combo and a DSI panel
|
||||
dts: stm32mp157c-dk2
|
||||
|
||||
5. Build Procedure
|
||||
==================
|
||||
|
||||
|
@ -90,12 +104,14 @@ the supported device trees for stm32mp157 are:
|
|||
# export KBUILD_OUTPUT=/path/to/output
|
||||
|
||||
for example: use one output directory for each configuration
|
||||
# export KBUILD_OUTPUT=stm32mp15_trusted
|
||||
# export KBUILD_OUTPUT=stm32mp15_basic
|
||||
|
||||
4. Configure the U-Boot:
|
||||
4. Configure U-Boot:
|
||||
|
||||
# make <defconfig_file>
|
||||
|
||||
- For trusted boot mode : "stm32mp15_trusted_defconfig"
|
||||
- For basic boot mode: "stm32mp15_basic_defconfig"
|
||||
|
||||
5. Configure the device-tree and build the U-Boot image:
|
||||
|
@ -104,16 +120,26 @@ the supported device trees for stm32mp157 are:
|
|||
|
||||
|
||||
example:
|
||||
basic boot on ev1
|
||||
a) trusted boot on ev1
|
||||
# export KBUILD_OUTPUT=stm32mp15_trusted
|
||||
# make stm32mp15_trusted_defconfig
|
||||
# make DEVICE_TREE=stm32mp157c-ev1 all
|
||||
|
||||
b) basic boot on ev1
|
||||
# export KBUILD_OUTPUT=stm32mp15_basic
|
||||
# make stm32mp15_basic_defconfig
|
||||
# make DEVICE_TREE=stm32mp157c-ev1 all
|
||||
|
||||
basic boot on ed1
|
||||
c) basic boot on ed1
|
||||
# export KBUILD_OUTPUT=stm32mp15_basic
|
||||
# make stm32mp15_basic_defconfig
|
||||
# make DEVICE_TREE=stm32mp157c-ed1 all
|
||||
|
||||
d) basic boot on dk2
|
||||
# export KBUILD_OUTPUT=stm32mp15_basic
|
||||
# make stm32mp15_basic_defconfig
|
||||
# make DEVICE_TREE=stm32mp157c-dk2 all
|
||||
|
||||
6. Output files
|
||||
|
||||
BootRom and TF-A expect binaries with STM32 image header
|
||||
|
@ -122,6 +148,11 @@ the supported device trees for stm32mp157 are:
|
|||
So in the output directory (selected by KBUILD_OUTPUT),
|
||||
you can found the needed files:
|
||||
|
||||
a) For Trusted boot
|
||||
+ FSBL = tf-a.stm32 (provided by TF-A compilation)
|
||||
+ SSBL = u-boot.stm32
|
||||
|
||||
b) For Basic boot
|
||||
+ FSBL = spl/u-boot-spl.stm32
|
||||
+ SSBL = u-boot.img
|
||||
|
||||
|
@ -135,13 +166,22 @@ You can select the boot mode, on the board ed1 with the switch SW1
|
|||
-----------------------------------
|
||||
Reserved 0 0 0
|
||||
NOR 0 0 1
|
||||
SD-Card 1 1 1
|
||||
SD-Card 1 0 1
|
||||
eMMC 0 1 0
|
||||
NAND 0 1 1
|
||||
Recovery 1 1 0
|
||||
Recovery 0 0 0
|
||||
|
||||
- on board DK1/DK2 with the switch SW1 : BOOT0, BOOT2
|
||||
(BOOT1 forced to 0, NOR not supported)
|
||||
|
||||
--------------------------
|
||||
Boot Mode BOOT2 BOOT0
|
||||
--------------------------
|
||||
Reserved 1 0
|
||||
SD-Card 1 1
|
||||
Recovery 0 0
|
||||
|
||||
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).
|
||||
|
@ -158,14 +198,14 @@ The minimal requirements for STMP32MP1 boot up to U-Boot are:
|
|||
- one ssbl partition for U-Boot
|
||||
|
||||
Then the minimal GPT partition is:
|
||||
----- ------- --------- -------------
|
||||
| Num | Name | Size | Content |
|
||||
----- ------- -------- --------------
|
||||
----- ------- --------- --------------
|
||||
| Num | Name | Size | Content |
|
||||
----- ------- -------- ---------------
|
||||
| 1 | fsbl1 | 256 KiB | TF-A or SPL |
|
||||
| 2 | fsbl2 | 256 KiB | TF-A or SPL |
|
||||
| 3 | ssbl | enought | U-Boot |
|
||||
| * | - | - | Boot/Rootfs|
|
||||
----- ------- --------- -------------
|
||||
| 3 | ssbl | enought | U-Boot |
|
||||
| * | - | - | Boot/Rootfs |
|
||||
----- ------- --------- --------------
|
||||
|
||||
(*) add bootable partition for extlinux.conf
|
||||
following Generic Distribution
|
||||
|
@ -189,7 +229,7 @@ for example: with gpt table with 128 entries
|
|||
|
||||
you can add other partitions for kernel
|
||||
one partition rootfs for example:
|
||||
-n 3:5154: -c 4:rootfs
|
||||
-n 4:5154: -c 4:rootfs \
|
||||
|
||||
c) copy the FSBL (2 times) and SSBL file on the correct partition.
|
||||
in this example in partition 1 to 3
|
||||
|
@ -199,6 +239,11 @@ for example: with gpt table with 128 entries
|
|||
# dd if=u-boot-spl.stm32 of=/dev/mmcblk0p2
|
||||
# dd if=u-boot.img of=/dev/mmcblk0p3
|
||||
|
||||
for trusted boot mode :
|
||||
# dd if=tf-a.stm32 of=/dev/mmcblk0p1
|
||||
# dd if=tf-a.stm32 of=/dev/mmcblk0p2
|
||||
# dd if=u-boot.stm32 of=/dev/mmcblk0p3
|
||||
|
||||
To boot from SDCard, select BootPinMode = 1 1 1 and reset.
|
||||
|
||||
8. Prepare eMMC
|
||||
|
@ -208,7 +253,7 @@ You can use U-Boot to copy binary in eMMC.
|
|||
In the next example, you need to boot from SDCARD and the images (u-boot-spl.stm32, u-boot.img)
|
||||
are presents on SDCARD (mmc 0) in ext4 partition 4 (bootfs).
|
||||
|
||||
To boot from SDCard, select BootPinMode = 1 1 1 and reset.
|
||||
To boot from SDCard, select BootPinMode = 1 0 1 and reset.
|
||||
|
||||
Then you update the eMMC with the next U-Boot command :
|
||||
|
||||
|
@ -227,7 +272,7 @@ b) copy SPL on eMMC on firts boot partition
|
|||
# mmc write ${fileaddr} 0 200
|
||||
# mmc partconf 1 1 1 0
|
||||
|
||||
b) copy U-Boot in first GPT partition of eMMC
|
||||
c) copy U-Boot in first GPT partition of eMMC
|
||||
|
||||
# ext4load mmc 0:4 0xC0000000 u-boot.img
|
||||
# mmc dev 1
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/arch/ddr.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/stpmu1.h>
|
||||
#include <power/stpmic1.h>
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_BOARD_INIT
|
||||
void board_debug_uart_init(void)
|
||||
|
@ -37,64 +37,65 @@ void board_debug_uart_init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PMIC_STPMU1
|
||||
#ifdef CONFIG_PMIC_STPMIC1
|
||||
int board_ddr_power_init(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_PMIC,
|
||||
DM_GET_DRIVER(pmic_stpmu1), &dev);
|
||||
DM_GET_DRIVER(pmic_stpmic1), &dev);
|
||||
if (ret)
|
||||
/* No PMIC on board */
|
||||
return 0;
|
||||
|
||||
/* Set LDO3 to sync mode */
|
||||
ret = pmic_reg_read(dev, STPMU1_LDOX_CTRL_REG(STPMU1_LDO3));
|
||||
/* VTT = Set LDO3 to sync mode */
|
||||
ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= ~STPMU1_LDO3_MODE;
|
||||
ret &= ~STPMU1_LDO12356_OUTPUT_MASK;
|
||||
ret |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT;
|
||||
ret &= ~STPMIC1_LDO3_MODE;
|
||||
ret &= ~STPMIC1_LDO12356_VOUT_MASK;
|
||||
ret |= STPMIC1_LDO_VOUT(STPMIC1_LDO3_DDR_SEL);
|
||||
|
||||
ret = pmic_reg_write(dev, STPMU1_LDOX_CTRL_REG(STPMU1_LDO3),
|
||||
ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
|
||||
ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Set BUCK2 to 1.35V */
|
||||
/* VDD_DDR = Set BUCK2 to 1.35V */
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMU1_BUCKX_CTRL_REG(STPMU1_BUCK2),
|
||||
STPMU1_BUCK_OUTPUT_MASK,
|
||||
STPMU1_BUCK2_1350000V);
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
|
||||
STPMIC1_BUCK_VOUT_MASK,
|
||||
STPMIC1_BUCK2_1350000V);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Enable BUCK2 and VREF */
|
||||
/* Enable VDD_DDR = BUCK2 */
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMU1_BUCKX_CTRL_REG(STPMU1_BUCK2),
|
||||
STPMU1_BUCK_EN, STPMU1_BUCK_EN);
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
|
||||
STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
ret = pmic_clrsetbits(dev, STPMU1_VREF_CTRL_REG,
|
||||
STPMU1_VREF_EN, STPMU1_VREF_EN);
|
||||
/* Enable VREF */
|
||||
ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR,
|
||||
STPMIC1_VREF_ENA, STPMIC1_VREF_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
/* Enable LDO3 */
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMU1_LDOX_CTRL_REG(STPMU1_LDO3),
|
||||
STPMU1_LDO_EN, STPMU1_LDO_EN);
|
||||
STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
|
||||
STPMIC1_LDO_ENA, STPMIC1_LDO_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -11,22 +11,22 @@
|
|||
#include <asm/io.h>
|
||||
#include <post.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/stpmu1.h>
|
||||
#include <power/stpmic1.h>
|
||||
#include <asm/arch/ddr.h>
|
||||
|
||||
void spl_board_init(void)
|
||||
{
|
||||
/* Keep vdd on during the reset cycle */
|
||||
#if defined(CONFIG_PMIC_STPMU1) && defined(CONFIG_SPL_POWER_SUPPORT)
|
||||
#if defined(CONFIG_PMIC_STPMIC1) && defined(CONFIG_SPL_POWER_SUPPORT)
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_PMIC,
|
||||
DM_GET_DRIVER(pmic_stpmu1), &dev);
|
||||
DM_GET_DRIVER(pmic_stpmic1), &dev);
|
||||
if (!ret)
|
||||
pmic_clrsetbits(dev,
|
||||
STPMU1_MASK_RESET_BUCK,
|
||||
STPMU1_MASK_RESET_BUCK3,
|
||||
STPMU1_MASK_RESET_BUCK3);
|
||||
STPMIC1_BUCKS_MRST_CR,
|
||||
STPMIC1_MRST_BUCK(STPMIC1_BUCK3),
|
||||
STPMIC1_MRST_BUCK(STPMIC1_BUCK3));
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -2,20 +2,57 @@
|
|||
/*
|
||||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <led.h>
|
||||
#include <adc.h>
|
||||
#include <config.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <generic-phy.h>
|
||||
#include <led.h>
|
||||
#include <misc.h>
|
||||
#include <phy.h>
|
||||
#include <reset.h>
|
||||
#include <syscon.h>
|
||||
#include <usb.h>
|
||||
#include <asm/arch/stm32.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/stm32.h>
|
||||
#include <power/regulator.h>
|
||||
#include <usb/dwc2_udc.h>
|
||||
|
||||
/* SYSCFG registers */
|
||||
#define SYSCFG_BOOTR 0x00
|
||||
#define SYSCFG_PMCSETR 0x04
|
||||
#define SYSCFG_IOCTRLSETR 0x18
|
||||
#define SYSCFG_ICNR 0x1C
|
||||
#define SYSCFG_CMPCR 0x20
|
||||
#define SYSCFG_CMPENSETR 0x24
|
||||
#define SYSCFG_PMCCLRR 0x44
|
||||
|
||||
#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
|
||||
#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
|
||||
|
||||
#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
|
||||
#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
|
||||
#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
|
||||
#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
|
||||
#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
|
||||
|
||||
#define SYSCFG_CMPCR_SW_CTRL BIT(1)
|
||||
#define SYSCFG_CMPCR_READY BIT(8)
|
||||
|
||||
#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
|
||||
|
||||
#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16)
|
||||
#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17)
|
||||
|
||||
#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)
|
||||
|
||||
/*
|
||||
* Get a global data pointer
|
||||
*/
|
||||
|
@ -26,6 +63,98 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
#define STM32MP_GGPIO 0x38
|
||||
#define STM32MP_GGPIO_VBUS_SENSING BIT(21)
|
||||
|
||||
#define USB_WARNING_LOW_THRESHOLD_UV 660000
|
||||
#define USB_START_LOW_THRESHOLD_UV 1230000
|
||||
#define USB_START_HIGH_THRESHOLD_UV 2100000
|
||||
|
||||
int checkboard(void)
|
||||
{
|
||||
int ret;
|
||||
char *mode;
|
||||
u32 otp;
|
||||
struct udevice *dev;
|
||||
const char *fdt_compat;
|
||||
int fdt_compat_len;
|
||||
|
||||
if (IS_ENABLED(CONFIG_STM32MP1_TRUSTED))
|
||||
mode = "trusted";
|
||||
else
|
||||
mode = "basic";
|
||||
|
||||
printf("Board: stm32mp1 in %s mode", mode);
|
||||
fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
|
||||
&fdt_compat_len);
|
||||
if (fdt_compat && fdt_compat_len)
|
||||
printf(" (%s)", fdt_compat);
|
||||
puts("\n");
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_MISC,
|
||||
DM_GET_DRIVER(stm32mp_bsec),
|
||||
&dev);
|
||||
|
||||
if (!ret)
|
||||
ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
|
||||
&otp, sizeof(otp));
|
||||
if (!ret && otp) {
|
||||
printf("Board: MB%04x Var%d Rev.%c-%02d\n",
|
||||
otp >> 16,
|
||||
(otp >> 12) & 0xF,
|
||||
((otp >> 8) & 0xF) - 1 + 'A',
|
||||
otp & 0xF);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void board_key_check(void)
|
||||
{
|
||||
#if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG)
|
||||
ofnode node;
|
||||
struct gpio_desc gpio;
|
||||
enum forced_boot_mode boot_mode = BOOT_NORMAL;
|
||||
|
||||
node = ofnode_path("/config");
|
||||
if (!ofnode_valid(node)) {
|
||||
debug("%s: no /config node?\n", __func__);
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_FASTBOOT
|
||||
if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
|
||||
&gpio, GPIOD_IS_IN)) {
|
||||
debug("%s: could not find a /config/st,fastboot-gpios\n",
|
||||
__func__);
|
||||
} else {
|
||||
if (dm_gpio_get_value(&gpio)) {
|
||||
puts("Fastboot key pressed, ");
|
||||
boot_mode = BOOT_FASTBOOT;
|
||||
}
|
||||
|
||||
dm_gpio_free(NULL, &gpio);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_CMD_STM32PROG
|
||||
if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
|
||||
&gpio, GPIOD_IS_IN)) {
|
||||
debug("%s: could not find a /config/st,stm32prog-gpios\n",
|
||||
__func__);
|
||||
} else {
|
||||
if (dm_gpio_get_value(&gpio)) {
|
||||
puts("STM32Programmer key pressed, ");
|
||||
boot_mode = BOOT_STM32PROG;
|
||||
}
|
||||
dm_gpio_free(NULL, &gpio);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (boot_mode != BOOT_NORMAL) {
|
||||
puts("entering download mode...\n");
|
||||
clrsetbits_le32(TAMP_BOOT_CONTEXT,
|
||||
TAMP_BOOT_FORCED_MASK,
|
||||
boot_mode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct dwc2_plat_otg_data stm32mp_otg_data = {
|
||||
.usb_gusbcfg = STM32MP_GUSBCFG,
|
||||
};
|
||||
|
@ -170,6 +299,145 @@ clk_err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int get_led(struct udevice **dev, char *led_string)
|
||||
{
|
||||
char *led_name;
|
||||
int ret;
|
||||
|
||||
led_name = fdtdec_get_config_string(gd->fdt_blob, led_string);
|
||||
if (!led_name) {
|
||||
pr_debug("%s: could not find %s config string\n",
|
||||
__func__, led_string);
|
||||
return -ENOENT;
|
||||
}
|
||||
ret = led_get_by_label(led_name, dev);
|
||||
if (ret) {
|
||||
debug("%s: get=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_led(enum led_state_t cmd)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = get_led(&dev, "u-boot,boot-led");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = led_set_state(dev, cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int board_check_usb_power(void)
|
||||
{
|
||||
struct ofnode_phandle_args adc_args;
|
||||
struct udevice *adc;
|
||||
struct udevice *led;
|
||||
ofnode node;
|
||||
unsigned int raw;
|
||||
int max_uV = 0;
|
||||
int ret, uV, adc_count;
|
||||
u8 i, nb_blink;
|
||||
|
||||
node = ofnode_path("/config");
|
||||
if (!ofnode_valid(node)) {
|
||||
debug("%s: no /config node?\n", __func__);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the ADC channels devices and get measurement
|
||||
* for each of them
|
||||
*/
|
||||
adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd",
|
||||
"#io-channel-cells");
|
||||
if (adc_count < 0) {
|
||||
if (adc_count == -ENOENT)
|
||||
return 0;
|
||||
|
||||
pr_err("%s: can't find adc channel (%d)\n", __func__,
|
||||
adc_count);
|
||||
|
||||
return adc_count;
|
||||
}
|
||||
|
||||
for (i = 0; i < adc_count; i++) {
|
||||
if (ofnode_parse_phandle_with_args(node, "st,adc_usb_pd",
|
||||
"#io-channel-cells", 0, i,
|
||||
&adc_args)) {
|
||||
pr_debug("%s: can't find /config/st,adc_usb_pd\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_ofnode(UCLASS_ADC, adc_args.node,
|
||||
&adc);
|
||||
|
||||
if (ret) {
|
||||
pr_err("%s: Can't get adc device(%d)\n", __func__,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adc_channel_single_shot(adc->name, adc_args.args[0],
|
||||
&raw);
|
||||
if (ret) {
|
||||
pr_err("%s: single shot failed for %s[%d]!\n",
|
||||
__func__, adc->name, adc_args.args[0]);
|
||||
return ret;
|
||||
}
|
||||
/* Convert to uV */
|
||||
if (!adc_raw_to_uV(adc, raw, &uV)) {
|
||||
if (uV > max_uV)
|
||||
max_uV = uV;
|
||||
pr_debug("%s: %s[%02d] = %u, %d uV\n", __func__,
|
||||
adc->name, adc_args.args[0], raw, uV);
|
||||
} else {
|
||||
pr_err("%s: Can't get uV value for %s[%d]\n",
|
||||
__func__, adc->name, adc_args.args[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If highest value is inside 1.23 Volts and 2.10 Volts, that means
|
||||
* board is plugged on an USB-C 3A power supply and boot process can
|
||||
* continue.
|
||||
*/
|
||||
if (max_uV > USB_START_LOW_THRESHOLD_UV &&
|
||||
max_uV < USB_START_HIGH_THRESHOLD_UV)
|
||||
return 0;
|
||||
|
||||
/* Display warning message and make u-boot,error-led blinking */
|
||||
pr_err("\n*******************************************\n");
|
||||
|
||||
if (max_uV < USB_WARNING_LOW_THRESHOLD_UV) {
|
||||
pr_err("* WARNING 500mA power supply detected *\n");
|
||||
nb_blink = 2;
|
||||
} else {
|
||||
pr_err("* WARNING 1.5A power supply detected *\n");
|
||||
nb_blink = 3;
|
||||
}
|
||||
|
||||
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)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < nb_blink * 2; i++) {
|
||||
led_set_state(led, LEDST_TOGGLE);
|
||||
mdelay(125);
|
||||
}
|
||||
led_set_state(led, LEDST_ON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_usb_cleanup(int index, enum usb_init_type init)
|
||||
{
|
||||
/* Reset usbotg */
|
||||
|
@ -180,19 +448,146 @@ int board_usb_cleanup(int index, enum usb_init_type init)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int board_late_init(void)
|
||||
static void sysconf_init(void)
|
||||
{
|
||||
return 0;
|
||||
#ifndef CONFIG_STM32MP1_TRUSTED
|
||||
u8 *syscfg;
|
||||
#ifdef CONFIG_DM_REGULATOR
|
||||
struct udevice *pwr_dev;
|
||||
struct udevice *pwr_reg;
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
u32 otp = 0;
|
||||
#endif
|
||||
u32 bootr;
|
||||
|
||||
syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
|
||||
|
||||
/* interconnect update : select master using the port 1 */
|
||||
/* LTDC = AXI_M9 */
|
||||
/* GPU = AXI_M8 */
|
||||
/* today information is hardcoded in U-Boot */
|
||||
writel(BIT(9), syscfg + SYSCFG_ICNR);
|
||||
|
||||
/* disable Pull-Down for boot pin connected to VDD */
|
||||
bootr = readl(syscfg + SYSCFG_BOOTR);
|
||||
bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT);
|
||||
bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
|
||||
writel(bootr, syscfg + SYSCFG_BOOTR);
|
||||
|
||||
#ifdef CONFIG_DM_REGULATOR
|
||||
/* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
|
||||
* and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
|
||||
* The customer will have to disable this for low frequencies
|
||||
* or if AFMUX is selected but the function not used, typically for
|
||||
* TRACE. Otherwise, impact on power consumption.
|
||||
*
|
||||
* WARNING:
|
||||
* enabling High Speed mode while VDD>2.7V
|
||||
* with the OTP product_below_2v5 (OTP 18, BIT 13)
|
||||
* erroneously set to 1 can damage the IC!
|
||||
* => U-Boot set the register only if VDD < 2.7V (in DT)
|
||||
* but this value need to be consistent with board design
|
||||
*/
|
||||
ret = syscon_get_by_driver_data(STM32MP_SYSCON_PWR, &pwr_dev);
|
||||
if (!ret) {
|
||||
ret = uclass_get_device_by_driver(UCLASS_MISC,
|
||||
DM_GET_DRIVER(stm32mp_bsec),
|
||||
&dev);
|
||||
if (ret) {
|
||||
pr_err("Can't find stm32mp_bsec driver\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = misc_read(dev, STM32_BSEC_SHADOW(18), &otp, 4);
|
||||
if (!ret)
|
||||
otp = otp & BIT(13);
|
||||
|
||||
/* get VDD = pwr-supply */
|
||||
ret = device_get_supply_regulator(pwr_dev, "pwr-supply",
|
||||
&pwr_reg);
|
||||
|
||||
/* check if VDD is Low Voltage */
|
||||
if (!ret) {
|
||||
if (regulator_get_value(pwr_reg) < 2700000) {
|
||||
writel(SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
|
||||
SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
|
||||
SYSCFG_IOCTRLSETR_HSLVEN_ETH |
|
||||
SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
|
||||
SYSCFG_IOCTRLSETR_HSLVEN_SPI,
|
||||
syscfg + SYSCFG_IOCTRLSETR);
|
||||
|
||||
if (!otp)
|
||||
pr_err("product_below_2v5=0: HSLVEN protected by HW\n");
|
||||
} else {
|
||||
if (otp)
|
||||
pr_err("product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n");
|
||||
}
|
||||
} else {
|
||||
debug("VDD unknown");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* activate automatic I/O compensation
|
||||
* warning: need to ensure CSI enabled and ready in clock driver
|
||||
*/
|
||||
writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR);
|
||||
|
||||
while (!(readl(syscfg + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY))
|
||||
;
|
||||
clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* board dependent setup after realloc */
|
||||
int board_init(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
|
||||
/* address of boot parameters */
|
||||
gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100;
|
||||
|
||||
/* probe all PINCTRL for hog */
|
||||
for (uclass_first_device(UCLASS_PINCTRL, &dev);
|
||||
dev;
|
||||
uclass_next_device(&dev)) {
|
||||
pr_debug("probe pincontrol = %s\n", dev->name);
|
||||
}
|
||||
|
||||
board_key_check();
|
||||
|
||||
sysconf_init();
|
||||
|
||||
if (IS_ENABLED(CONFIG_LED))
|
||||
led_default_state();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_late_init(void)
|
||||
{
|
||||
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
|
||||
const void *fdt_compat;
|
||||
int fdt_compat_len;
|
||||
|
||||
fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
|
||||
&fdt_compat_len);
|
||||
if (fdt_compat && fdt_compat_len) {
|
||||
if (strncmp(fdt_compat, "st,", 3) != 0)
|
||||
env_set("board_name", fdt_compat);
|
||||
else
|
||||
env_set("board_name", fdt_compat + 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* for DK1/DK2 boards */
|
||||
board_check_usb_power();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void board_quiesce_devices(void)
|
||||
{
|
||||
setup_led(LEDST_OFF);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_STM32MP=y
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x2000
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x3000
|
||||
CONFIG_SPL_MMC_SUPPORT=y
|
||||
CONFIG_SPL=y
|
||||
CONFIG_TARGET_STM32MP1=y
|
||||
CONFIG_DISTRO_DEFAULTS=y
|
||||
CONFIG_NR_DRAM_BANKS=1
|
||||
CONFIG_FIT=y
|
||||
CONFIG_BOOTCOMMAND="run bootcmd_stm32mp"
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=3
|
||||
CONFIG_SPL_I2C_SUPPORT=y
|
||||
|
@ -18,8 +19,10 @@ CONFIG_SYS_PROMPT="STM32MP> "
|
|||
# CONFIG_CMD_EXPORTENV is not set
|
||||
# CONFIG_CMD_IMPORTENV is not set
|
||||
CONFIG_CMD_MEMINFO=y
|
||||
CONFIG_CMD_MEMTEST=y
|
||||
CONFIG_CMD_ADC=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_DFU=y
|
||||
CONFIG_CMD_FUSE=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_GPT=y
|
||||
|
@ -27,12 +30,21 @@ CONFIG_CMD_I2C=y
|
|||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_USB=y
|
||||
CONFIG_CMD_USB_MASS_STORAGE=y
|
||||
CONFIG_CMD_CACHE=y
|
||||
CONFIG_CMD_TIME=y
|
||||
CONFIG_CMD_TIMER=y
|
||||
CONFIG_CMD_PMIC=y
|
||||
CONFIG_CMD_REGULATOR=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
# CONFIG_SPL_DOS_PARTITION is not set
|
||||
CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
|
||||
CONFIG_STM32_ADC=y
|
||||
CONFIG_USB_FUNCTION_FASTBOOT=y
|
||||
CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
|
||||
CONFIG_FASTBOOT_BUF_SIZE=0x02000000
|
||||
CONFIG_FASTBOOT_USB_DEV=1
|
||||
CONFIG_FASTBOOT_FLASH=y
|
||||
CONFIG_FASTBOOT_FLASH_MMC_DEV=1
|
||||
CONFIG_DM_HWSPINLOCK=y
|
||||
CONFIG_HWSPINLOCK_STM32=y
|
||||
CONFIG_DM_I2C=y
|
||||
|
@ -43,15 +55,16 @@ CONFIG_DM_MMC=y
|
|||
CONFIG_STM32_SDMMC2=y
|
||||
CONFIG_PHY=y
|
||||
CONFIG_PHY_STM32_USBPHYC=y
|
||||
# CONFIG_PINCTRL_FULL is not set
|
||||
CONFIG_PINCONF=y
|
||||
# CONFIG_SPL_PINCTRL_FULL is not set
|
||||
CONFIG_PINCTRL_STMFX=y
|
||||
CONFIG_DM_PMIC=y
|
||||
# CONFIG_SPL_PMIC_CHILDREN is not set
|
||||
CONFIG_PMIC_STPMU1=y
|
||||
CONFIG_PMIC_STPMIC1=y
|
||||
CONFIG_DM_REGULATOR_FIXED=y
|
||||
CONFIG_DM_REGULATOR_GPIO=y
|
||||
CONFIG_DM_REGULATOR_STM32_VREFBUF=y
|
||||
CONFIG_DM_REGULATOR_STPMU1=y
|
||||
CONFIG_DM_REGULATOR_STPMIC1=y
|
||||
CONFIG_SERIAL_RX_BUFFER=y
|
||||
CONFIG_STM32_SERIAL=y
|
||||
CONFIG_USB=y
|
||||
|
@ -64,4 +77,3 @@ CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
|
|||
CONFIG_USB_GADGET_VENDOR_NUM=0x0483
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0x5720
|
||||
CONFIG_USB_GADGET_DWC2_OTG=y
|
||||
CONFIG_USB_GADGET_DOWNLOAD=y
|
||||
|
|
70
configs/stm32mp15_trusted_defconfig
Normal file
70
configs/stm32mp15_trusted_defconfig
Normal file
|
@ -0,0 +1,70 @@
|
|||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_STM32MP=y
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x3000
|
||||
CONFIG_TARGET_STM32MP1=y
|
||||
CONFIG_DISTRO_DEFAULTS=y
|
||||
CONFIG_FIT=y
|
||||
CONFIG_BOOTCOMMAND="run bootcmd_stm32mp"
|
||||
CONFIG_SYS_PROMPT="STM32MP> "
|
||||
# CONFIG_CMD_BOOTD is not set
|
||||
# CONFIG_CMD_ELF is not set
|
||||
# CONFIG_CMD_IMI is not set
|
||||
# CONFIG_CMD_XIMG is not set
|
||||
# CONFIG_CMD_EXPORTENV is not set
|
||||
# CONFIG_CMD_IMPORTENV is not set
|
||||
CONFIG_CMD_MEMINFO=y
|
||||
CONFIG_CMD_MEMTEST=y
|
||||
CONFIG_CMD_ADC=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_DFU=y
|
||||
CONFIG_CMD_FUSE=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_USB=y
|
||||
CONFIG_CMD_USB_MASS_STORAGE=y
|
||||
CONFIG_CMD_CACHE=y
|
||||
CONFIG_CMD_TIME=y
|
||||
CONFIG_CMD_TIMER=y
|
||||
CONFIG_CMD_PMIC=y
|
||||
CONFIG_CMD_REGULATOR=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
|
||||
CONFIG_STM32_ADC=y
|
||||
CONFIG_USB_FUNCTION_FASTBOOT=y
|
||||
CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
|
||||
CONFIG_FASTBOOT_BUF_SIZE=0x02000000
|
||||
CONFIG_FASTBOOT_USB_DEV=1
|
||||
CONFIG_FASTBOOT_FLASH=y
|
||||
CONFIG_FASTBOOT_FLASH_MMC_DEV=1
|
||||
CONFIG_DM_HWSPINLOCK=y
|
||||
CONFIG_HWSPINLOCK_STM32=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_SYS_I2C_STM32F7=y
|
||||
CONFIG_LED=y
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_DM_MMC=y
|
||||
CONFIG_STM32_SDMMC2=y
|
||||
CONFIG_PHY=y
|
||||
CONFIG_PHY_STM32_USBPHYC=y
|
||||
CONFIG_PINCONF=y
|
||||
CONFIG_PINCTRL_STMFX=y
|
||||
CONFIG_DM_PMIC=y
|
||||
CONFIG_PMIC_STPMIC1=y
|
||||
CONFIG_DM_REGULATOR_FIXED=y
|
||||
CONFIG_DM_REGULATOR_GPIO=y
|
||||
CONFIG_DM_REGULATOR_STM32_VREFBUF=y
|
||||
CONFIG_DM_REGULATOR_STPMIC1=y
|
||||
CONFIG_SERIAL_RX_BUFFER=y
|
||||
CONFIG_STM32_SERIAL=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_DM_USB=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_EHCI_GENERIC=y
|
||||
CONFIG_USB_DWC2=y
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x0483
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0x5720
|
||||
CONFIG_USB_GADGET_DWC2_OTG=y
|
59
doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt
Normal file
59
doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt
Normal file
|
@ -0,0 +1,59 @@
|
|||
STMicroelectronics Flexible Memory Controller 2 (FMC2)
|
||||
NAND Interface
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be one of:
|
||||
* st,stm32mp15-fmc2
|
||||
- reg: NAND flash controller memory areas.
|
||||
First region contains the register location.
|
||||
Regions 2 to 4 respectively contain the data, command,
|
||||
and address space for CS0.
|
||||
Regions 5 to 7 contain the same areas for CS1.
|
||||
- interrupts: The interrupt number
|
||||
- pinctrl-0: Standard Pinctrl phandle (see: pinctrl/pinctrl-bindings.txt)
|
||||
- clocks: The clock needed by the NAND flash controller
|
||||
|
||||
Optional properties:
|
||||
- resets: Reference to a reset controller asserting the FMC controller
|
||||
- dmas: DMA specifiers (see: dma/stm32-mdma.txt)
|
||||
- dma-names: Must be "tx", "rx" and "ecc"
|
||||
|
||||
Optional children nodes:
|
||||
Children nodes represent the available NAND chips.
|
||||
|
||||
Optional properties:
|
||||
- nand-on-flash-bbt: see nand.txt
|
||||
- nand-ecc-strength: see nand.txt
|
||||
- nand-ecc-step-size: see nand.txt
|
||||
|
||||
The following ECC strength and step size are currently supported:
|
||||
- nand-ecc-strength = <1>, nand-ecc-step-size = <512> (Hamming)
|
||||
- nand-ecc-strength = <4>, nand-ecc-step-size = <512> (BCH4)
|
||||
- nand-ecc-strength = <8>, nand-ecc-step-size = <512> (BCH8) (default)
|
||||
|
||||
Example:
|
||||
|
||||
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>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&fmc_pins_a>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
nand@0 {
|
||||
reg = <0>;
|
||||
nand-on-flash-bbt;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
};
|
||||
};
|
|
@ -15,10 +15,12 @@
|
|||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
#include <dt-bindings/clock/stm32mp1-clksrc.h>
|
||||
|
||||
#ifndef CONFIG_STM32MP1_TRUSTED
|
||||
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
|
||||
/* activate clock tree initialization in the driver */
|
||||
#define STM32MP1_CLOCK_TREE_INIT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MAX_HSI_HZ 64000000
|
||||
|
||||
|
|
|
@ -9,8 +9,10 @@
|
|||
#include <errno.h>
|
||||
#include <dm/device.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <power/stpmic1.h>
|
||||
|
||||
#define STM32MP_OTP_BANK 0
|
||||
#define STM32MP_NVM_BANK 1
|
||||
|
||||
/*
|
||||
* The 'fuse' command API
|
||||
|
@ -34,6 +36,13 @@ int fuse_read(u32 bank, u32 word, u32 *val)
|
|||
ret = 0;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_PMIC_STPMIC1
|
||||
case STM32MP_NVM_BANK:
|
||||
*val = 0;
|
||||
ret = stpmic1_shadow_read_byte(word, (u8 *)val);
|
||||
break;
|
||||
#endif /* CONFIG_PMIC_STPMIC1 */
|
||||
|
||||
default:
|
||||
printf("stm32mp %s: wrong value for bank %i\n", __func__, bank);
|
||||
ret = -EINVAL;
|
||||
|
@ -62,6 +71,12 @@ int fuse_prog(u32 bank, u32 word, u32 val)
|
|||
ret = 0;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_PMIC_STPMIC1
|
||||
case STM32MP_NVM_BANK:
|
||||
ret = stpmic1_nvm_write_byte(word, (u8 *)&val);
|
||||
break;
|
||||
#endif /* CONFIG_PMIC_STPMIC1 */
|
||||
|
||||
default:
|
||||
printf("stm32mp %s: wrong value for bank %i\n", __func__, bank);
|
||||
ret = -EINVAL;
|
||||
|
@ -89,6 +104,13 @@ int fuse_sense(u32 bank, u32 word, u32 *val)
|
|||
ret = 0;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_PMIC_STPMIC1
|
||||
case STM32MP_NVM_BANK:
|
||||
*val = 0;
|
||||
ret = stpmic1_nvm_read_byte(word, (u8 *)val);
|
||||
break;
|
||||
#endif /* CONFIG_PMIC_STPMIC1 */
|
||||
|
||||
default:
|
||||
printf("stm32mp %s: wrong value for bank %i\n", __func__, bank);
|
||||
ret = -EINVAL;
|
||||
|
@ -117,6 +139,12 @@ int fuse_override(u32 bank, u32 word, u32 val)
|
|||
ret = 0;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_PMIC_STPMIC1
|
||||
case STM32MP_NVM_BANK:
|
||||
ret = stpmic1_shadow_write_byte(word, (u8 *)&val);
|
||||
break;
|
||||
#endif /* CONFIG_PMIC_STPMIC1 */
|
||||
|
||||
default:
|
||||
printf("stm32mp %s: wrong value for bank %i\n",
|
||||
__func__, bank);
|
||||
|
|
|
@ -256,6 +256,17 @@ config NAND_ZYNQ_USE_BOOTLOADER1_TIMINGS
|
|||
This flag prevent U-boot reconfigure NAND flash controller and reuse
|
||||
the NAND timing from 1st stage bootloader.
|
||||
|
||||
config NAND_STM32_FMC2
|
||||
bool "Support for NAND controller on STM32MP SoCs"
|
||||
depends on ARCH_STM32MP
|
||||
select SYS_NAND_SELF_INIT
|
||||
imply CMD_NAND
|
||||
help
|
||||
Enables support for NAND Flash chips on SoCs containing the FMC2
|
||||
NAND controller. This controller is found on STM32MP SoCs.
|
||||
The controller supports a maximum 8k page size and supports
|
||||
a maximum 8-bit correction error per sector of 512 bytes.
|
||||
|
||||
comment "Generic NAND options"
|
||||
|
||||
config SYS_NAND_BLOCK_SIZE
|
||||
|
|
|
@ -65,6 +65,7 @@ obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
|
|||
obj-$(CONFIG_NAND_PLAT) += nand_plat.o
|
||||
obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
|
||||
obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o
|
||||
obj-$(CONFIG_NAND_STM32_FMC2) += stm32_fmc2_nand.o
|
||||
|
||||
else # minimal SPL drivers
|
||||
|
||||
|
|
1092
drivers/mtd/nand/raw/stm32_fmc2_nand.c
Normal file
1092
drivers/mtd/nand/raw/stm32_fmc2_nand.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -209,6 +209,25 @@ config PINCTRL_STM32
|
|||
the GPIO definitions and pin control functions for each available
|
||||
multiplex function.
|
||||
|
||||
config PINCTRL_STMFX
|
||||
bool "STMicroelectronics STMFX I2C GPIO expander pinctrl driver"
|
||||
depends on DM && PINCTRL_FULL
|
||||
help
|
||||
I2C driver for STMicroelectronics Multi-Function eXpander (STMFX)
|
||||
GPIO expander.
|
||||
Supports pin multiplexing control on stm32 SoCs.
|
||||
|
||||
The driver is controlled by a device tree node which contains both
|
||||
the GPIO definitions and pin control functions for each available
|
||||
multiplex function.
|
||||
|
||||
config SPL_PINCTRL_STMFX
|
||||
bool "STMicroelectronics STMFX I2C GPIO expander pinctrl driver in SPL"
|
||||
depends on SPL_PINCTRL_FULL
|
||||
help
|
||||
This option is an SPL-variant of the SPL_PINCTRL_STMFX option.
|
||||
See the help of PINCTRL_STMFX for details.
|
||||
|
||||
config ASPEED_AST2500_PINCTRL
|
||||
bool "Aspeed AST2500 pin control driver"
|
||||
depends on DM && PINCTRL_GENERIC && ASPEED_AST2500
|
||||
|
|
|
@ -22,4 +22,5 @@ obj-$(CONFIG_ARCH_MVEBU) += mvebu/
|
|||
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
|
||||
obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o
|
||||
obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o
|
||||
obj-$(CONFIG_$(SPL_)PINCTRL_STMFX) += pinctrl-stmfx.o
|
||||
obj-y += broadcom/
|
||||
|
|
431
drivers/pinctrl/pinctrl-stmfx.c
Normal file
431
drivers/pinctrl/pinctrl-stmfx.c
Normal file
|
@ -0,0 +1,431 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* Driver for STMicroelectronics Multi-Function eXpander (STMFX) GPIO expander
|
||||
* based on Linux driver : pinctrl/pinctrl-stmfx.c
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <dm/device.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/lists.h>
|
||||
#include <dm/pinctrl.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <power/regulator.h>
|
||||
|
||||
/* STMFX pins = GPIO[15:0] + aGPIO[7:0] */
|
||||
#define STMFX_MAX_GPIO 16
|
||||
#define STMFX_MAX_AGPIO 8
|
||||
|
||||
/* General */
|
||||
#define STMFX_REG_CHIP_ID 0x00 /* R */
|
||||
#define STMFX_REG_FW_VERSION_MSB 0x01 /* R */
|
||||
#define STMFX_REG_FW_VERSION_LSB 0x02 /* R */
|
||||
#define STMFX_REG_SYS_CTRL 0x40 /* RW */
|
||||
|
||||
/* MFX boot time is around 10ms, so after reset, we have to wait this delay */
|
||||
#define STMFX_BOOT_TIME_MS 10
|
||||
|
||||
/* GPIOs expander */
|
||||
/* GPIO_STATE1 0x10, GPIO_STATE2 0x11, GPIO_STATE3 0x12 */
|
||||
#define STMFX_REG_GPIO_STATE 0x10 /* R */
|
||||
/* GPIO_DIR1 0x60, GPIO_DIR2 0x61, GPIO_DIR3 0x63 */
|
||||
#define STMFX_REG_GPIO_DIR 0x60 /* RW */
|
||||
/* GPIO_TYPE1 0x64, GPIO_TYPE2 0x65, GPIO_TYPE3 0x66 */
|
||||
#define STMFX_REG_GPIO_TYPE 0x64 /* RW */
|
||||
/* GPIO_PUPD1 0x68, GPIO_PUPD2 0x69, GPIO_PUPD3 0x6A */
|
||||
#define STMFX_REG_GPIO_PUPD 0x68 /* RW */
|
||||
/* GPO_SET1 0x6C, GPO_SET2 0x6D, GPO_SET3 0x6E */
|
||||
#define STMFX_REG_GPO_SET 0x6C /* RW */
|
||||
/* GPO_CLR1 0x70, GPO_CLR2 0x71, GPO_CLR3 0x72 */
|
||||
#define STMFX_REG_GPO_CLR 0x70 /* RW */
|
||||
|
||||
/* STMFX_REG_CHIP_ID bitfields */
|
||||
#define STMFX_REG_CHIP_ID_MASK GENMASK(7, 0)
|
||||
|
||||
/* STMFX_REG_SYS_CTRL bitfields */
|
||||
#define STMFX_REG_SYS_CTRL_GPIO_EN BIT(0)
|
||||
#define STMFX_REG_SYS_CTRL_ALTGPIO_EN BIT(3)
|
||||
#define STMFX_REG_SYS_CTRL_SWRST BIT(7)
|
||||
|
||||
#define NR_GPIO_REGS 3
|
||||
#define NR_GPIOS_PER_REG 8
|
||||
#define get_reg(offset) ((offset) / NR_GPIOS_PER_REG)
|
||||
#define get_shift(offset) ((offset) % NR_GPIOS_PER_REG)
|
||||
#define get_mask(offset) (BIT(get_shift(offset)))
|
||||
|
||||
struct stmfx_pinctrl {
|
||||
struct udevice *gpio;
|
||||
};
|
||||
|
||||
static int stmfx_read(struct udevice *dev, uint offset)
|
||||
{
|
||||
return dm_i2c_reg_read(dev_get_parent(dev), offset);
|
||||
}
|
||||
|
||||
static int stmfx_write(struct udevice *dev, uint offset, unsigned int val)
|
||||
{
|
||||
return dm_i2c_reg_write(dev_get_parent(dev), offset, val);
|
||||
}
|
||||
|
||||
static int stmfx_gpio_get(struct udevice *dev, unsigned int offset)
|
||||
{
|
||||
u32 reg = STMFX_REG_GPIO_STATE + get_reg(offset);
|
||||
u32 mask = get_mask(offset);
|
||||
int ret;
|
||||
|
||||
ret = stmfx_read(dev, reg);
|
||||
|
||||
return ret < 0 ? ret : !!(ret & mask);
|
||||
}
|
||||
|
||||
static int stmfx_gpio_set(struct udevice *dev, unsigned int offset, int value)
|
||||
{
|
||||
u32 reg = value ? STMFX_REG_GPO_SET : STMFX_REG_GPO_CLR;
|
||||
u32 mask = get_mask(offset);
|
||||
|
||||
return stmfx_write(dev, reg + get_reg(offset), mask);
|
||||
}
|
||||
|
||||
static int stmfx_gpio_get_function(struct udevice *dev, unsigned int offset)
|
||||
{
|
||||
u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset);
|
||||
u32 mask = get_mask(offset);
|
||||
int ret;
|
||||
|
||||
ret = stmfx_read(dev, reg);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* On stmfx, gpio pins direction is (0)input, (1)output. */
|
||||
|
||||
return ret & mask ? GPIOF_OUTPUT : GPIOF_INPUT;
|
||||
}
|
||||
|
||||
static int stmfx_gpio_direction_input(struct udevice *dev, unsigned int offset)
|
||||
{
|
||||
u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset);
|
||||
u32 mask = get_mask(offset);
|
||||
int ret;
|
||||
|
||||
ret = stmfx_read(dev, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= ~mask;
|
||||
|
||||
return stmfx_write(dev, reg, ret & ~mask);
|
||||
}
|
||||
|
||||
static int stmfx_gpio_direction_output(struct udevice *dev,
|
||||
unsigned int offset, int value)
|
||||
{
|
||||
u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset);
|
||||
u32 mask = get_mask(offset);
|
||||
int ret;
|
||||
|
||||
ret = stmfx_gpio_set(dev, offset, value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = stmfx_read(dev, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return stmfx_write(dev, reg, ret | mask);
|
||||
}
|
||||
|
||||
static int stmfx_gpio_probe(struct udevice *dev)
|
||||
{
|
||||
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
struct ofnode_phandle_args args;
|
||||
u8 sys_ctrl;
|
||||
|
||||
uc_priv->bank_name = "stmfx";
|
||||
uc_priv->gpio_count = STMFX_MAX_GPIO + STMFX_MAX_AGPIO;
|
||||
if (!dev_read_phandle_with_args(dev, "gpio-ranges",
|
||||
NULL, 3, 0, &args)) {
|
||||
uc_priv->gpio_count = args.args[2];
|
||||
}
|
||||
|
||||
/* enable GPIO function */
|
||||
sys_ctrl = STMFX_REG_SYS_CTRL_GPIO_EN;
|
||||
if (uc_priv->gpio_count > STMFX_MAX_GPIO)
|
||||
sys_ctrl |= STMFX_REG_SYS_CTRL_ALTGPIO_EN;
|
||||
stmfx_write(dev, STMFX_REG_SYS_CTRL, sys_ctrl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_gpio_ops stmfx_gpio_ops = {
|
||||
.set_value = stmfx_gpio_set,
|
||||
.get_value = stmfx_gpio_get,
|
||||
.get_function = stmfx_gpio_get_function,
|
||||
.direction_input = stmfx_gpio_direction_input,
|
||||
.direction_output = stmfx_gpio_direction_output,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stmfx_gpio) = {
|
||||
.name = "stmfx-gpio",
|
||||
.id = UCLASS_GPIO,
|
||||
.probe = stmfx_gpio_probe,
|
||||
.ops = &stmfx_gpio_ops,
|
||||
};
|
||||
|
||||
#if CONFIG_IS_ENABLED(PINCONF)
|
||||
static const struct pinconf_param stmfx_pinctrl_conf_params[] = {
|
||||
{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
|
||||
{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 0 },
|
||||
{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 0 },
|
||||
{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 0 },
|
||||
{ "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
|
||||
{ "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
|
||||
{ "output-high", PIN_CONFIG_OUTPUT, 1 },
|
||||
{ "output-low", PIN_CONFIG_OUTPUT, 0 },
|
||||
};
|
||||
|
||||
static int stmfx_pinctrl_set_pupd(struct udevice *dev,
|
||||
unsigned int pin, u32 pupd)
|
||||
{
|
||||
u8 reg = STMFX_REG_GPIO_PUPD + get_reg(pin);
|
||||
u32 mask = get_mask(pin);
|
||||
int ret;
|
||||
|
||||
ret = stmfx_read(dev, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = (ret & ~mask) | (pupd ? mask : 0);
|
||||
|
||||
return stmfx_write(dev, reg, ret);
|
||||
}
|
||||
|
||||
static int stmfx_pinctrl_set_type(struct udevice *dev,
|
||||
unsigned int pin, u32 type)
|
||||
{
|
||||
u8 reg = STMFX_REG_GPIO_TYPE + get_reg(pin);
|
||||
u32 mask = get_mask(pin);
|
||||
int ret;
|
||||
|
||||
ret = stmfx_read(dev, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = (ret & ~mask) | (type ? mask : 0);
|
||||
|
||||
return stmfx_write(dev, reg, ret);
|
||||
}
|
||||
|
||||
static int stmfx_pinctrl_conf_set(struct udevice *dev, unsigned int pin,
|
||||
unsigned int param, unsigned int arg)
|
||||
{
|
||||
int ret, dir;
|
||||
struct stmfx_pinctrl *plat = dev_get_platdata(dev);
|
||||
|
||||
dir = stmfx_gpio_get_function(plat->gpio, pin);
|
||||
|
||||
if (dir < 0)
|
||||
return dir;
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
ret = stmfx_pinctrl_set_pupd(dev, pin, 0);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
ret = stmfx_pinctrl_set_pupd(dev, pin, 1);
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
if (dir == GPIOF_OUTPUT)
|
||||
ret = stmfx_pinctrl_set_type(dev, pin, 1);
|
||||
else
|
||||
ret = stmfx_pinctrl_set_type(dev, pin, 0);
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
||||
if (dir == GPIOF_OUTPUT)
|
||||
ret = stmfx_pinctrl_set_type(dev, pin, 0);
|
||||
else
|
||||
ret = stmfx_pinctrl_set_type(dev, pin, 1);
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
ret = stmfx_gpio_direction_output(plat->gpio, pin, arg);
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int stmfx_pinctrl_get_pins_count(struct udevice *dev)
|
||||
{
|
||||
struct stmfx_pinctrl *plat = dev_get_platdata(dev);
|
||||
struct gpio_dev_priv *uc_priv;
|
||||
|
||||
uc_priv = dev_get_uclass_priv(plat->gpio);
|
||||
|
||||
return uc_priv->gpio_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* STMFX pins[15:0] are called "gpio[15:0]"
|
||||
* and STMFX pins[23:16] are called "agpio[7:0]"
|
||||
*/
|
||||
#define MAX_PIN_NAME_LEN 7
|
||||
static char pin_name[MAX_PIN_NAME_LEN];
|
||||
static const char *stmfx_pinctrl_get_pin_name(struct udevice *dev,
|
||||
unsigned int selector)
|
||||
{
|
||||
if (selector < STMFX_MAX_GPIO)
|
||||
snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
|
||||
else
|
||||
snprintf(pin_name, MAX_PIN_NAME_LEN, "agpio%u", selector - 16);
|
||||
return pin_name;
|
||||
}
|
||||
|
||||
static int stmfx_pinctrl_get_pin_muxing(struct udevice *dev,
|
||||
unsigned int selector,
|
||||
char *buf, int size)
|
||||
{
|
||||
struct stmfx_pinctrl *plat = dev_get_platdata(dev);
|
||||
int func;
|
||||
|
||||
func = stmfx_gpio_get_function(plat->gpio, selector);
|
||||
if (func < 0)
|
||||
return func;
|
||||
|
||||
snprintf(buf, size, "%s", func == GPIOF_INPUT ? "input" : "output");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stmfx_pinctrl_bind(struct udevice *dev)
|
||||
{
|
||||
struct stmfx_pinctrl *plat = dev_get_platdata(dev);
|
||||
|
||||
return device_bind_driver_to_node(dev->parent,
|
||||
"stmfx-gpio", "stmfx-gpio",
|
||||
dev_ofnode(dev), &plat->gpio);
|
||||
};
|
||||
|
||||
static int stmfx_pinctrl_probe(struct udevice *dev)
|
||||
{
|
||||
struct stmfx_pinctrl *plat = dev_get_platdata(dev);
|
||||
|
||||
return device_probe(plat->gpio);
|
||||
};
|
||||
|
||||
const struct pinctrl_ops stmfx_pinctrl_ops = {
|
||||
.get_pins_count = stmfx_pinctrl_get_pins_count,
|
||||
.get_pin_name = stmfx_pinctrl_get_pin_name,
|
||||
.set_state = pinctrl_generic_set_state,
|
||||
.get_pin_muxing = stmfx_pinctrl_get_pin_muxing,
|
||||
#if CONFIG_IS_ENABLED(PINCONF)
|
||||
.pinconf_set = stmfx_pinctrl_conf_set,
|
||||
.pinconf_num_params = ARRAY_SIZE(stmfx_pinctrl_conf_params),
|
||||
.pinconf_params = stmfx_pinctrl_conf_params,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct udevice_id stmfx_pinctrl_match[] = {
|
||||
{ .compatible = "st,stmfx-0300-pinctrl", },
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stmfx_pinctrl) = {
|
||||
.name = "stmfx-pinctrl",
|
||||
.id = UCLASS_PINCTRL,
|
||||
.of_match = of_match_ptr(stmfx_pinctrl_match),
|
||||
.bind = stmfx_pinctrl_bind,
|
||||
.probe = stmfx_pinctrl_probe,
|
||||
.ops = &stmfx_pinctrl_ops,
|
||||
.platdata_auto_alloc_size = sizeof(struct stmfx_pinctrl),
|
||||
};
|
||||
|
||||
static int stmfx_chip_init(struct udevice *dev)
|
||||
{
|
||||
u8 id;
|
||||
u8 version[2];
|
||||
int ret;
|
||||
struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
|
||||
|
||||
id = dm_i2c_reg_read(dev, STMFX_REG_CHIP_ID);
|
||||
if (id < 0) {
|
||||
dev_err(dev, "error reading chip id: %d\n", id);
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* Check that ID is the complement of the I2C address:
|
||||
* STMFX I2C address follows the 7-bit format (MSB), that's why
|
||||
* client->addr is shifted.
|
||||
*
|
||||
* STMFX_I2C_ADDR| STMFX | Linux
|
||||
* input pin | I2C device address | I2C device address
|
||||
*---------------------------------------------------------
|
||||
* 0 | b: 1000 010x h:0x84 | 0x42
|
||||
* 1 | b: 1000 011x h:0x86 | 0x43
|
||||
*/
|
||||
if (FIELD_GET(STMFX_REG_CHIP_ID_MASK, ~id) != (chip->chip_addr << 1)) {
|
||||
dev_err(dev, "unknown chip id: %#x\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = dm_i2c_read(dev, STMFX_REG_FW_VERSION_MSB,
|
||||
version, sizeof(version));
|
||||
if (ret) {
|
||||
dev_err(dev, "error reading fw version: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(dev, "STMFX id: %#x, fw version: %x.%02x\n",
|
||||
id, version[0], version[1]);
|
||||
|
||||
ret = dm_i2c_reg_read(dev, STMFX_REG_SYS_CTRL);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = dm_i2c_reg_write(dev, STMFX_REG_SYS_CTRL,
|
||||
ret | STMFX_REG_SYS_CTRL_SWRST);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mdelay(STMFX_BOOT_TIME_MS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stmfx_probe(struct udevice *dev)
|
||||
{
|
||||
struct udevice *vdd;
|
||||
int ret;
|
||||
|
||||
ret = device_get_supply_regulator(dev, "vdd-supply", &vdd);
|
||||
if (ret && ret != -ENOENT) {
|
||||
dev_err(dev, "vdd regulator error:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (!ret) {
|
||||
ret = regulator_set_enable(vdd, true);
|
||||
if (ret) {
|
||||
dev_err(dev, "vdd enable failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return stmfx_chip_init(dev);
|
||||
}
|
||||
|
||||
static const struct udevice_id stmfx_match[] = {
|
||||
{ .compatible = "st,stmfx-0300", },
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stmfx) = {
|
||||
.name = "stmfx",
|
||||
.id = UCLASS_I2C_GENERIC,
|
||||
.of_match = of_match_ptr(stmfx_match),
|
||||
.probe = stmfx_probe,
|
||||
.bind = dm_scan_fdt_dev,
|
||||
};
|
|
@ -231,10 +231,10 @@ config DM_PMIC_TPS65910
|
|||
DC-DC converter, 8 LDOs and a RTC. This driver binds the SMPS and LDO
|
||||
pmic children.
|
||||
|
||||
config PMIC_STPMU1
|
||||
bool "Enable support for STMicroelectronics STPMU1 PMIC"
|
||||
config PMIC_STPMIC1
|
||||
bool "Enable support for STMicroelectronics STPMIC1 PMIC"
|
||||
depends on DM_PMIC && DM_I2C
|
||||
---help---
|
||||
The STPMU1 PMIC provides 4 BUCKs, 6 LDOs, 1 VREF and 2 power switches.
|
||||
The STPMIC1 PMIC provides 4 BUCKs, 6 LDOs, 1 VREF and 2 power switches.
|
||||
It is accessed via an I2C interface. The device is used with STM32MP1
|
||||
SoCs. This driver implements register read/write operations.
|
||||
|
|
|
@ -23,7 +23,7 @@ obj-$(CONFIG_DM_PMIC_TPS65910) += pmic_tps65910_dm.o
|
|||
obj-$(CONFIG_$(SPL_)PMIC_PALMAS) += palmas.o
|
||||
obj-$(CONFIG_$(SPL_)PMIC_LP873X) += lp873x.o
|
||||
obj-$(CONFIG_$(SPL_)PMIC_LP87565) += lp87565.o
|
||||
obj-$(CONFIG_PMIC_STPMU1) += stpmu1.o
|
||||
obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o
|
||||
|
||||
obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
|
||||
obj-$(CONFIG_POWER_MAX77696) += pmic_max77696.o
|
||||
|
|
255
drivers/power/pmic/stpmic1.c
Normal file
255
drivers/power/pmic/stpmic1.c
Normal file
|
@ -0,0 +1,255 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <sysreset.h>
|
||||
#include <dm/device.h>
|
||||
#include <dm/lists.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/stpmic1.h>
|
||||
|
||||
#define STPMIC1_NUM_OF_REGS 0x100
|
||||
|
||||
#define STPMIC1_NVM_SIZE 8
|
||||
#define STPMIC1_NVM_POLL_TIMEOUT 100000
|
||||
#define STPMIC1_NVM_START_ADDRESS 0xf8
|
||||
|
||||
enum pmic_nvm_op {
|
||||
SHADOW_READ,
|
||||
SHADOW_WRITE,
|
||||
NVM_READ,
|
||||
NVM_WRITE,
|
||||
};
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_REGULATOR)
|
||||
static const struct pmic_child_info stpmic1_children_info[] = {
|
||||
{ .prefix = "ldo", .driver = "stpmic1_ldo" },
|
||||
{ .prefix = "buck", .driver = "stpmic1_buck" },
|
||||
{ .prefix = "vref_ddr", .driver = "stpmic1_vref_ddr" },
|
||||
{ .prefix = "pwr_sw", .driver = "stpmic1_pwr_sw" },
|
||||
{ .prefix = "boost", .driver = "stpmic1_boost" },
|
||||
{ },
|
||||
};
|
||||
#endif /* DM_REGULATOR */
|
||||
|
||||
static int stpmic1_reg_count(struct udevice *dev)
|
||||
{
|
||||
return STPMIC1_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static int stpmic1_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buff, len);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: failed to write register %#x :%d",
|
||||
__func__, reg, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmic1_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buff, len);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: failed to read register %#x : %d",
|
||||
__func__, reg, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmic1_bind(struct udevice *dev)
|
||||
{
|
||||
#if CONFIG_IS_ENABLED(DM_REGULATOR)
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
dev_dbg(dev, "regulators subnode not found!");
|
||||
return -ENXIO;
|
||||
}
|
||||
dev_dbg(dev, "found regulators subnode\n");
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node,
|
||||
stpmic1_children_info);
|
||||
if (!children)
|
||||
dev_dbg(dev, "no child found\n");
|
||||
#endif /* DM_REGULATOR */
|
||||
|
||||
if (CONFIG_IS_ENABLED(SYSRESET))
|
||||
return device_bind_driver(dev, "stpmic1-sysreset",
|
||||
"stpmic1-sysreset", NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops stpmic1_ops = {
|
||||
.reg_count = stpmic1_reg_count,
|
||||
.read = stpmic1_read,
|
||||
.write = stpmic1_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id stpmic1_ids[] = {
|
||||
{ .compatible = "st,stpmic1" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_stpmic1) = {
|
||||
.name = "stpmic1_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = stpmic1_ids,
|
||||
.bind = stpmic1_bind,
|
||||
.ops = &stpmic1_ops,
|
||||
};
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
static int stpmic1_nvm_rw(u8 addr, u8 *buf, int buf_len, enum pmic_nvm_op op)
|
||||
{
|
||||
struct udevice *dev;
|
||||
unsigned long timeout;
|
||||
u8 cmd = STPMIC1_NVM_CMD_READ;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_PMIC,
|
||||
DM_GET_DRIVER(pmic_stpmic1), &dev);
|
||||
if (ret)
|
||||
/* No PMIC on power discrete board */
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (addr < STPMIC1_NVM_START_ADDRESS)
|
||||
return -EACCES;
|
||||
|
||||
if (op == SHADOW_READ)
|
||||
return pmic_read(dev, addr, buf, buf_len);
|
||||
|
||||
if (op == SHADOW_WRITE)
|
||||
return pmic_write(dev, addr, buf, buf_len);
|
||||
|
||||
if (op == NVM_WRITE) {
|
||||
cmd = STPMIC1_NVM_CMD_PROGRAM;
|
||||
|
||||
ret = pmic_write(dev, addr, buf, buf_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = pmic_reg_read(dev, STPMIC1_NVM_CR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = pmic_reg_write(dev, STPMIC1_NVM_CR, ret | cmd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
timeout = timer_get_us() + STPMIC1_NVM_POLL_TIMEOUT;
|
||||
for (;;) {
|
||||
ret = pmic_reg_read(dev, STPMIC1_NVM_SR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!(ret & STPMIC1_NVM_BUSY))
|
||||
break;
|
||||
|
||||
if (time_after(timer_get_us(), timeout))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret & STPMIC1_NVM_BUSY)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
if (op == NVM_READ) {
|
||||
ret = pmic_read(dev, addr, buf, buf_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stpmic1_shadow_read_byte(u8 addr, u8 *buf)
|
||||
{
|
||||
return stpmic1_nvm_rw(addr, buf, 1, SHADOW_READ);
|
||||
}
|
||||
|
||||
int stpmic1_shadow_write_byte(u8 addr, u8 *buf)
|
||||
{
|
||||
return stpmic1_nvm_rw(addr, buf, 1, SHADOW_WRITE);
|
||||
}
|
||||
|
||||
int stpmic1_nvm_read_byte(u8 addr, u8 *buf)
|
||||
{
|
||||
return stpmic1_nvm_rw(addr, buf, 1, NVM_READ);
|
||||
}
|
||||
|
||||
int stpmic1_nvm_write_byte(u8 addr, u8 *buf)
|
||||
{
|
||||
return stpmic1_nvm_rw(addr, buf, 1, NVM_WRITE);
|
||||
}
|
||||
|
||||
int stpmic1_nvm_read_all(u8 *buf, int buf_len)
|
||||
{
|
||||
if (buf_len != STPMIC1_NVM_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
return stpmic1_nvm_rw(STPMIC1_NVM_START_ADDRESS,
|
||||
buf, buf_len, NVM_READ);
|
||||
}
|
||||
|
||||
int stpmic1_nvm_write_all(u8 *buf, int buf_len)
|
||||
{
|
||||
if (buf_len != STPMIC1_NVM_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
return stpmic1_nvm_rw(STPMIC1_NVM_START_ADDRESS,
|
||||
buf, buf_len, NVM_WRITE);
|
||||
}
|
||||
#endif /* CONFIG_SPL_BUILD */
|
||||
|
||||
#ifdef CONFIG_SYSRESET
|
||||
static int stpmic1_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||
{
|
||||
struct udevice *pmic_dev;
|
||||
int ret;
|
||||
|
||||
if (type != SYSRESET_POWER)
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_PMIC,
|
||||
DM_GET_DRIVER(pmic_stpmic1),
|
||||
&pmic_dev);
|
||||
|
||||
if (ret)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = pmic_reg_read(pmic_dev, STPMIC1_MAIN_CR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = pmic_reg_write(pmic_dev, STPMIC1_MAIN_CR,
|
||||
ret | STPMIC1_SWOFF | STPMIC1_RREQ_EN);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
static struct sysreset_ops stpmic1_sysreset_ops = {
|
||||
.request = stpmic1_sysreset_request,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmic1_sysreset) = {
|
||||
.name = "stpmic1-sysreset",
|
||||
.id = UCLASS_SYSRESET,
|
||||
.ops = &stpmic1_sysreset_ops,
|
||||
};
|
||||
#endif
|
|
@ -1,95 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/stpmu1.h>
|
||||
|
||||
#define STMPU1_NUM_OF_REGS 0x100
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
static const struct pmic_child_info stpmu1_children_info[] = {
|
||||
{ .prefix = "ldo", .driver = "stpmu1_ldo" },
|
||||
{ .prefix = "buck", .driver = "stpmu1_buck" },
|
||||
{ .prefix = "vref_ddr", .driver = "stpmu1_vref_ddr" },
|
||||
{ .prefix = "pwr_sw", .driver = "stpmu1_pwr_sw" },
|
||||
{ .prefix = "boost", .driver = "stpmu1_boost" },
|
||||
{ },
|
||||
};
|
||||
#endif /* CONFIG_SPL_BUILD */
|
||||
|
||||
static int stpmu1_reg_count(struct udevice *dev)
|
||||
{
|
||||
return STMPU1_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static int stpmu1_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buff, len);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: failed to write register %#x :%d",
|
||||
__func__, reg, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmu1_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buff, len);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: failed to read register %#x : %d",
|
||||
__func__, reg, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmu1_bind(struct udevice *dev)
|
||||
{
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
dev_dbg(dev, "regulators subnode not found!\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
dev_dbg(dev, "found regulators subnode\n");
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node,
|
||||
stpmu1_children_info);
|
||||
if (!children)
|
||||
dev_dbg(dev, "no child found\n");
|
||||
#endif /* CONFIG_SPL_BUILD */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops stpmu1_ops = {
|
||||
.reg_count = stpmu1_reg_count,
|
||||
.read = stpmu1_read,
|
||||
.write = stpmu1_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id stpmu1_ids[] = {
|
||||
{ .compatible = "st,stpmu1" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_stpmu1) = {
|
||||
.name = "stpmu1_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = stpmu1_ids,
|
||||
.bind = stpmu1_bind,
|
||||
.ops = &stpmu1_ops,
|
||||
};
|
|
@ -244,11 +244,17 @@ config DM_REGULATOR_TPS65910
|
|||
regulator types of the TPS65910 (BUCK, BOOST and LDO). It implements
|
||||
the get/set api for value and enable.
|
||||
|
||||
config DM_REGULATOR_STPMU1
|
||||
bool "Enable driver for STPMU1 regulators"
|
||||
depends on DM_REGULATOR && PMIC_STPMU1
|
||||
config DM_REGULATOR_STPMIC1
|
||||
bool "Enable driver for STPMIC1 regulators"
|
||||
depends on DM_REGULATOR && PMIC_STPMIC1
|
||||
---help---
|
||||
Enable support for the regulator functions of the STPMU1 PMIC. The
|
||||
Enable support for the regulator functions of the STPMIC1 PMIC. The
|
||||
driver implements get/set api for the various BUCKS and LDOs supported
|
||||
by the PMIC device. This driver is controlled by a device tree node
|
||||
which includes voltage limits.
|
||||
|
||||
config SPL_DM_REGULATOR_STPMIC1
|
||||
bool "Enable driver for STPMIC1 regulators in SPL"
|
||||
depends on SPL_DM_REGULATOR && PMIC_STPMIC1
|
||||
help
|
||||
Enable support for the regulator functions of the STPMIC1 PMIC in SPL.
|
||||
|
|
|
@ -24,4 +24,4 @@ obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP873X) += lp873x_regulator.o
|
|||
obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP87565) += lp87565_regulator.o
|
||||
obj-$(CONFIG_$(SPL_)DM_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
|
||||
obj-$(CONFIG_DM_REGULATOR_TPS65910) += tps65910_regulator.o
|
||||
obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMU1) += stpmu1.o
|
||||
obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMIC1) += stpmic1.o
|
||||
|
|
672
drivers/power/regulator/stpmic1.c
Normal file
672
drivers/power/regulator/stpmic1.c
Normal file
|
@ -0,0 +1,672 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
||||
* Author: Christophe Kerello <christophe.kerello@st.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/stpmic1.h>
|
||||
|
||||
struct stpmic1_range {
|
||||
int min_uv;
|
||||
int min_sel;
|
||||
int max_sel;
|
||||
int step;
|
||||
};
|
||||
|
||||
struct stpmic1_output {
|
||||
const struct stpmic1_range *ranges;
|
||||
int nbranges;
|
||||
};
|
||||
|
||||
#define STPMIC1_MODE(_id, _val, _name) { \
|
||||
.id = _id, \
|
||||
.register_value = _val, \
|
||||
.name = _name, \
|
||||
}
|
||||
|
||||
#define STPMIC1_RANGE(_min_uv, _min_sel, _max_sel, _step) { \
|
||||
.min_uv = _min_uv, \
|
||||
.min_sel = _min_sel, \
|
||||
.max_sel = _max_sel, \
|
||||
.step = _step, \
|
||||
}
|
||||
|
||||
#define STPMIC1_OUTPUT(_ranges, _nbranges) { \
|
||||
.ranges = _ranges, \
|
||||
.nbranges = _nbranges, \
|
||||
}
|
||||
|
||||
static int stpmic1_output_find_uv(int sel,
|
||||
const struct stpmic1_output *output)
|
||||
{
|
||||
const struct stpmic1_range *range;
|
||||
int i;
|
||||
|
||||
for (i = 0, range = output->ranges;
|
||||
i < output->nbranges; i++, range++) {
|
||||
if (sel >= range->min_sel && sel <= range->max_sel)
|
||||
return range->min_uv +
|
||||
(sel - range->min_sel) * range->step;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int stpmic1_output_find_sel(int uv,
|
||||
const struct stpmic1_output *output)
|
||||
{
|
||||
const struct stpmic1_range *range;
|
||||
int i;
|
||||
|
||||
for (i = 0, range = output->ranges;
|
||||
i < output->nbranges; i++, range++) {
|
||||
if (uv == range->min_uv && !range->step)
|
||||
return range->min_sel;
|
||||
|
||||
if (uv >= range->min_uv &&
|
||||
uv <= range->min_uv +
|
||||
(range->max_sel - range->min_sel) * range->step)
|
||||
return range->min_sel +
|
||||
(uv - range->min_uv) / range->step;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* BUCK regulators
|
||||
*/
|
||||
|
||||
static const struct stpmic1_range buck1_ranges[] = {
|
||||
STPMIC1_RANGE(725000, 0, 4, 0),
|
||||
STPMIC1_RANGE(725000, 5, 36, 25000),
|
||||
STPMIC1_RANGE(1500000, 37, 63, 0),
|
||||
};
|
||||
|
||||
static const struct stpmic1_range buck2_ranges[] = {
|
||||
STPMIC1_RANGE(1000000, 0, 17, 0),
|
||||
STPMIC1_RANGE(1050000, 18, 19, 0),
|
||||
STPMIC1_RANGE(1100000, 20, 21, 0),
|
||||
STPMIC1_RANGE(1150000, 22, 23, 0),
|
||||
STPMIC1_RANGE(1200000, 24, 25, 0),
|
||||
STPMIC1_RANGE(1250000, 26, 27, 0),
|
||||
STPMIC1_RANGE(1300000, 28, 29, 0),
|
||||
STPMIC1_RANGE(1350000, 30, 31, 0),
|
||||
STPMIC1_RANGE(1400000, 32, 33, 0),
|
||||
STPMIC1_RANGE(1450000, 34, 35, 0),
|
||||
STPMIC1_RANGE(1500000, 36, 63, 0),
|
||||
};
|
||||
|
||||
static const struct stpmic1_range buck3_ranges[] = {
|
||||
STPMIC1_RANGE(1000000, 0, 19, 0),
|
||||
STPMIC1_RANGE(1100000, 20, 23, 0),
|
||||
STPMIC1_RANGE(1200000, 24, 27, 0),
|
||||
STPMIC1_RANGE(1300000, 28, 31, 0),
|
||||
STPMIC1_RANGE(1400000, 32, 35, 0),
|
||||
STPMIC1_RANGE(1500000, 36, 55, 100000),
|
||||
STPMIC1_RANGE(3400000, 56, 63, 0),
|
||||
};
|
||||
|
||||
static const struct stpmic1_range buck4_ranges[] = {
|
||||
STPMIC1_RANGE(600000, 0, 27, 25000),
|
||||
STPMIC1_RANGE(1300000, 28, 29, 0),
|
||||
STPMIC1_RANGE(1350000, 30, 31, 0),
|
||||
STPMIC1_RANGE(1400000, 32, 33, 0),
|
||||
STPMIC1_RANGE(1450000, 34, 35, 0),
|
||||
STPMIC1_RANGE(1500000, 36, 60, 100000),
|
||||
STPMIC1_RANGE(3900000, 61, 63, 0),
|
||||
};
|
||||
|
||||
/* BUCK: 1,2,3,4 - voltage ranges */
|
||||
static const struct stpmic1_output buck_voltage_range[] = {
|
||||
STPMIC1_OUTPUT(buck1_ranges, ARRAY_SIZE(buck1_ranges)),
|
||||
STPMIC1_OUTPUT(buck2_ranges, ARRAY_SIZE(buck2_ranges)),
|
||||
STPMIC1_OUTPUT(buck3_ranges, ARRAY_SIZE(buck3_ranges)),
|
||||
STPMIC1_OUTPUT(buck4_ranges, ARRAY_SIZE(buck4_ranges)),
|
||||
};
|
||||
|
||||
/* BUCK modes */
|
||||
static const struct dm_regulator_mode buck_modes[] = {
|
||||
STPMIC1_MODE(STPMIC1_PREG_MODE_HP, STPMIC1_PREG_MODE_HP, "HP"),
|
||||
STPMIC1_MODE(STPMIC1_PREG_MODE_LP, STPMIC1_PREG_MODE_LP, "LP"),
|
||||
};
|
||||
|
||||
static int stpmic1_buck_get_uv(struct udevice *dev, int buck)
|
||||
{
|
||||
int sel;
|
||||
|
||||
sel = pmic_reg_read(dev, STPMIC1_BUCKX_MAIN_CR(buck));
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
sel &= STPMIC1_BUCK_VOUT_MASK;
|
||||
sel >>= STPMIC1_BUCK_VOUT_SHIFT;
|
||||
|
||||
return stpmic1_output_find_uv(sel, &buck_voltage_range[buck]);
|
||||
}
|
||||
|
||||
static int stpmic1_buck_get_value(struct udevice *dev)
|
||||
{
|
||||
return stpmic1_buck_get_uv(dev->parent, dev->driver_data - 1);
|
||||
}
|
||||
|
||||
static int stpmic1_buck_set_value(struct udevice *dev, int uv)
|
||||
{
|
||||
int sel, buck = dev->driver_data - 1;
|
||||
|
||||
sel = stpmic1_output_find_sel(uv, &buck_voltage_range[buck]);
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
return pmic_clrsetbits(dev->parent,
|
||||
STPMIC1_BUCKX_MAIN_CR(buck),
|
||||
STPMIC1_BUCK_VOUT_MASK,
|
||||
sel << STPMIC1_BUCK_VOUT_SHIFT);
|
||||
}
|
||||
|
||||
static int stpmic1_buck_get_enable(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent,
|
||||
STPMIC1_BUCKX_MAIN_CR(dev->driver_data - 1));
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
return ret & STPMIC1_BUCK_ENA ? true : false;
|
||||
}
|
||||
|
||||
static int stpmic1_buck_set_enable(struct udevice *dev, bool enable)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
int delay = enable ? STPMIC1_DEFAULT_START_UP_DELAY_MS :
|
||||
STPMIC1_DEFAULT_STOP_DELAY_MS;
|
||||
int ret, uv;
|
||||
|
||||
/* if regulator is already in the wanted state, nothing to do */
|
||||
if (stpmic1_buck_get_enable(dev) == enable)
|
||||
return 0;
|
||||
|
||||
if (enable) {
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
uv = stpmic1_buck_get_value(dev);
|
||||
if (uv < uc_pdata->min_uV || uv > uc_pdata->max_uV)
|
||||
stpmic1_buck_set_value(dev, uc_pdata->min_uV);
|
||||
}
|
||||
|
||||
ret = pmic_clrsetbits(dev->parent,
|
||||
STPMIC1_BUCKX_MAIN_CR(dev->driver_data - 1),
|
||||
STPMIC1_BUCK_ENA, enable ? STPMIC1_BUCK_ENA : 0);
|
||||
mdelay(delay);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmic1_buck_get_mode(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent,
|
||||
STPMIC1_BUCKX_MAIN_CR(dev->driver_data - 1));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ret & STPMIC1_BUCK_PREG_MODE ? STPMIC1_PREG_MODE_LP :
|
||||
STPMIC1_PREG_MODE_HP;
|
||||
}
|
||||
|
||||
static int stpmic1_buck_set_mode(struct udevice *dev, int mode)
|
||||
{
|
||||
return pmic_clrsetbits(dev->parent,
|
||||
STPMIC1_BUCKX_MAIN_CR(dev->driver_data - 1),
|
||||
STPMIC1_BUCK_PREG_MODE,
|
||||
mode ? STPMIC1_BUCK_PREG_MODE : 0);
|
||||
}
|
||||
|
||||
static int stpmic1_buck_probe(struct udevice *dev)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
|
||||
if (!dev->driver_data || dev->driver_data > STPMIC1_MAX_BUCK)
|
||||
return -EINVAL;
|
||||
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
|
||||
uc_pdata->type = REGULATOR_TYPE_BUCK;
|
||||
uc_pdata->mode = (struct dm_regulator_mode *)buck_modes;
|
||||
uc_pdata->mode_count = ARRAY_SIZE(buck_modes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_regulator_ops stpmic1_buck_ops = {
|
||||
.get_value = stpmic1_buck_get_value,
|
||||
.set_value = stpmic1_buck_set_value,
|
||||
.get_enable = stpmic1_buck_get_enable,
|
||||
.set_enable = stpmic1_buck_set_enable,
|
||||
.get_mode = stpmic1_buck_get_mode,
|
||||
.set_mode = stpmic1_buck_set_mode,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmic1_buck) = {
|
||||
.name = "stpmic1_buck",
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &stpmic1_buck_ops,
|
||||
.probe = stpmic1_buck_probe,
|
||||
};
|
||||
|
||||
/*
|
||||
* LDO regulators
|
||||
*/
|
||||
|
||||
static const struct stpmic1_range ldo12_ranges[] = {
|
||||
STPMIC1_RANGE(1700000, 0, 7, 0),
|
||||
STPMIC1_RANGE(1700000, 8, 24, 100000),
|
||||
STPMIC1_RANGE(3300000, 25, 31, 0),
|
||||
};
|
||||
|
||||
static const struct stpmic1_range ldo3_ranges[] = {
|
||||
STPMIC1_RANGE(1700000, 0, 7, 0),
|
||||
STPMIC1_RANGE(1700000, 8, 24, 100000),
|
||||
STPMIC1_RANGE(3300000, 25, 30, 0),
|
||||
/* Sel 31 is special case when LDO3 is in mode sync_source (BUCK2/2) */
|
||||
};
|
||||
|
||||
static const struct stpmic1_range ldo5_ranges[] = {
|
||||
STPMIC1_RANGE(1700000, 0, 7, 0),
|
||||
STPMIC1_RANGE(1700000, 8, 30, 100000),
|
||||
STPMIC1_RANGE(3900000, 31, 31, 0),
|
||||
};
|
||||
|
||||
static const struct stpmic1_range ldo6_ranges[] = {
|
||||
STPMIC1_RANGE(900000, 0, 24, 100000),
|
||||
STPMIC1_RANGE(3300000, 25, 31, 0),
|
||||
};
|
||||
|
||||
/* LDO: 1,2,3,4,5,6 - voltage ranges */
|
||||
static const struct stpmic1_output ldo_voltage_range[] = {
|
||||
STPMIC1_OUTPUT(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)),
|
||||
STPMIC1_OUTPUT(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)),
|
||||
STPMIC1_OUTPUT(ldo3_ranges, ARRAY_SIZE(ldo3_ranges)),
|
||||
STPMIC1_OUTPUT(NULL, 0),
|
||||
STPMIC1_OUTPUT(ldo5_ranges, ARRAY_SIZE(ldo5_ranges)),
|
||||
STPMIC1_OUTPUT(ldo6_ranges, ARRAY_SIZE(ldo6_ranges)),
|
||||
};
|
||||
|
||||
/* LDO modes */
|
||||
static const struct dm_regulator_mode ldo_modes[] = {
|
||||
STPMIC1_MODE(STPMIC1_LDO_MODE_NORMAL,
|
||||
STPMIC1_LDO_MODE_NORMAL, "NORMAL"),
|
||||
STPMIC1_MODE(STPMIC1_LDO_MODE_BYPASS,
|
||||
STPMIC1_LDO_MODE_BYPASS, "BYPASS"),
|
||||
STPMIC1_MODE(STPMIC1_LDO_MODE_SINK_SOURCE,
|
||||
STPMIC1_LDO_MODE_SINK_SOURCE, "SINK SOURCE"),
|
||||
};
|
||||
|
||||
static int stpmic1_ldo_get_value(struct udevice *dev)
|
||||
{
|
||||
int sel, ldo = dev->driver_data - 1;
|
||||
|
||||
sel = pmic_reg_read(dev->parent, STPMIC1_LDOX_MAIN_CR(ldo));
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
/* ldo4 => 3,3V */
|
||||
if (ldo == STPMIC1_LDO4)
|
||||
return STPMIC1_LDO4_UV;
|
||||
|
||||
sel &= STPMIC1_LDO12356_VOUT_MASK;
|
||||
sel >>= STPMIC1_LDO12356_VOUT_SHIFT;
|
||||
|
||||
/* ldo3, sel = 31 => BUCK2/2 */
|
||||
if (ldo == STPMIC1_LDO3 && sel == STPMIC1_LDO3_DDR_SEL)
|
||||
return stpmic1_buck_get_uv(dev->parent, STPMIC1_BUCK2) / 2;
|
||||
|
||||
return stpmic1_output_find_uv(sel, &ldo_voltage_range[ldo]);
|
||||
}
|
||||
|
||||
static int stpmic1_ldo_set_value(struct udevice *dev, int uv)
|
||||
{
|
||||
int sel, ldo = dev->driver_data - 1;
|
||||
|
||||
/* ldo4 => not possible */
|
||||
if (ldo == STPMIC1_LDO4)
|
||||
return -EINVAL;
|
||||
|
||||
sel = stpmic1_output_find_sel(uv, &ldo_voltage_range[ldo]);
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
return pmic_clrsetbits(dev->parent,
|
||||
STPMIC1_LDOX_MAIN_CR(ldo),
|
||||
STPMIC1_LDO12356_VOUT_MASK,
|
||||
sel << STPMIC1_LDO12356_VOUT_SHIFT);
|
||||
}
|
||||
|
||||
static int stpmic1_ldo_get_enable(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent,
|
||||
STPMIC1_LDOX_MAIN_CR(dev->driver_data - 1));
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
return ret & STPMIC1_LDO_ENA ? true : false;
|
||||
}
|
||||
|
||||
static int stpmic1_ldo_set_enable(struct udevice *dev, bool enable)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
int delay = enable ? STPMIC1_DEFAULT_START_UP_DELAY_MS :
|
||||
STPMIC1_DEFAULT_STOP_DELAY_MS;
|
||||
int ret, uv;
|
||||
|
||||
/* if regulator is already in the wanted state, nothing to do */
|
||||
if (stpmic1_ldo_get_enable(dev) == enable)
|
||||
return 0;
|
||||
|
||||
if (enable) {
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
uv = stpmic1_ldo_get_value(dev);
|
||||
if (uv < uc_pdata->min_uV || uv > uc_pdata->max_uV)
|
||||
stpmic1_ldo_set_value(dev, uc_pdata->min_uV);
|
||||
}
|
||||
|
||||
ret = pmic_clrsetbits(dev->parent,
|
||||
STPMIC1_LDOX_MAIN_CR(dev->driver_data - 1),
|
||||
STPMIC1_LDO_ENA, enable ? STPMIC1_LDO_ENA : 0);
|
||||
mdelay(delay);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmic1_ldo_get_mode(struct udevice *dev)
|
||||
{
|
||||
int ret, ldo = dev->driver_data - 1;
|
||||
|
||||
if (ldo != STPMIC1_LDO3)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMIC1_LDOX_MAIN_CR(ldo));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret & STPMIC1_LDO3_MODE)
|
||||
return STPMIC1_LDO_MODE_BYPASS;
|
||||
|
||||
ret &= STPMIC1_LDO12356_VOUT_MASK;
|
||||
ret >>= STPMIC1_LDO12356_VOUT_SHIFT;
|
||||
|
||||
return ret == STPMIC1_LDO3_DDR_SEL ? STPMIC1_LDO_MODE_SINK_SOURCE :
|
||||
STPMIC1_LDO_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static int stpmic1_ldo_set_mode(struct udevice *dev, int mode)
|
||||
{
|
||||
int ret, ldo = dev->driver_data - 1;
|
||||
|
||||
if (ldo != STPMIC1_LDO3)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMIC1_LDOX_MAIN_CR(ldo));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (mode) {
|
||||
case STPMIC1_LDO_MODE_SINK_SOURCE:
|
||||
ret &= ~STPMIC1_LDO12356_VOUT_MASK;
|
||||
ret |= STPMIC1_LDO3_DDR_SEL << STPMIC1_LDO12356_VOUT_SHIFT;
|
||||
case STPMIC1_LDO_MODE_NORMAL:
|
||||
ret &= ~STPMIC1_LDO3_MODE;
|
||||
break;
|
||||
case STPMIC1_LDO_MODE_BYPASS:
|
||||
ret |= STPMIC1_LDO3_MODE;
|
||||
break;
|
||||
}
|
||||
|
||||
return pmic_reg_write(dev->parent, STPMIC1_LDOX_MAIN_CR(ldo), ret);
|
||||
}
|
||||
|
||||
static int stpmic1_ldo_probe(struct udevice *dev)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
|
||||
if (!dev->driver_data || dev->driver_data > STPMIC1_MAX_LDO)
|
||||
return -EINVAL;
|
||||
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
|
||||
uc_pdata->type = REGULATOR_TYPE_LDO;
|
||||
if (dev->driver_data - 1 == STPMIC1_LDO3) {
|
||||
uc_pdata->mode = (struct dm_regulator_mode *)ldo_modes;
|
||||
uc_pdata->mode_count = ARRAY_SIZE(ldo_modes);
|
||||
} else {
|
||||
uc_pdata->mode_count = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_regulator_ops stpmic1_ldo_ops = {
|
||||
.get_value = stpmic1_ldo_get_value,
|
||||
.set_value = stpmic1_ldo_set_value,
|
||||
.get_enable = stpmic1_ldo_get_enable,
|
||||
.set_enable = stpmic1_ldo_set_enable,
|
||||
.get_mode = stpmic1_ldo_get_mode,
|
||||
.set_mode = stpmic1_ldo_set_mode,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmic1_ldo) = {
|
||||
.name = "stpmic1_ldo",
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &stpmic1_ldo_ops,
|
||||
.probe = stpmic1_ldo_probe,
|
||||
};
|
||||
|
||||
/*
|
||||
* VREF DDR regulator
|
||||
*/
|
||||
|
||||
static int stpmic1_vref_ddr_get_value(struct udevice *dev)
|
||||
{
|
||||
/* BUCK2/2 */
|
||||
return stpmic1_buck_get_uv(dev->parent, STPMIC1_BUCK2) / 2;
|
||||
}
|
||||
|
||||
static int stpmic1_vref_ddr_get_enable(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMIC1_REFDDR_MAIN_CR);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
return ret & STPMIC1_VREF_ENA ? true : false;
|
||||
}
|
||||
|
||||
static int stpmic1_vref_ddr_set_enable(struct udevice *dev, bool enable)
|
||||
{
|
||||
int delay = enable ? STPMIC1_DEFAULT_START_UP_DELAY_MS :
|
||||
STPMIC1_DEFAULT_STOP_DELAY_MS;
|
||||
int ret;
|
||||
|
||||
/* if regulator is already in the wanted state, nothing to do */
|
||||
if (stpmic1_vref_ddr_get_enable(dev) == enable)
|
||||
return 0;
|
||||
|
||||
ret = pmic_clrsetbits(dev->parent, STPMIC1_REFDDR_MAIN_CR,
|
||||
STPMIC1_VREF_ENA, enable ? STPMIC1_VREF_ENA : 0);
|
||||
mdelay(delay);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmic1_vref_ddr_probe(struct udevice *dev)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
|
||||
uc_pdata->type = REGULATOR_TYPE_FIXED;
|
||||
uc_pdata->mode_count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_regulator_ops stpmic1_vref_ddr_ops = {
|
||||
.get_value = stpmic1_vref_ddr_get_value,
|
||||
.get_enable = stpmic1_vref_ddr_get_enable,
|
||||
.set_enable = stpmic1_vref_ddr_set_enable,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmic1_vref_ddr) = {
|
||||
.name = "stpmic1_vref_ddr",
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &stpmic1_vref_ddr_ops,
|
||||
.probe = stpmic1_vref_ddr_probe,
|
||||
};
|
||||
|
||||
/*
|
||||
* BOOST regulator
|
||||
*/
|
||||
|
||||
static int stpmic1_boost_get_enable(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMIC1_BST_SW_CR);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
return ret & STPMIC1_BST_ON ? true : false;
|
||||
}
|
||||
|
||||
static int stpmic1_boost_set_enable(struct udevice *dev, bool enable)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMIC1_BST_SW_CR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!enable && ret & STPMIC1_PWR_SW_ON)
|
||||
return -EINVAL;
|
||||
|
||||
/* if regulator is already in the wanted state, nothing to do */
|
||||
if (!!(ret & STPMIC1_BST_ON) == enable)
|
||||
return 0;
|
||||
|
||||
ret = pmic_clrsetbits(dev->parent, STPMIC1_BST_SW_CR,
|
||||
STPMIC1_BST_ON,
|
||||
enable ? STPMIC1_BST_ON : 0);
|
||||
if (enable)
|
||||
mdelay(STPMIC1_USB_BOOST_START_UP_DELAY_MS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmic1_boost_probe(struct udevice *dev)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
|
||||
uc_pdata->type = REGULATOR_TYPE_FIXED;
|
||||
uc_pdata->mode_count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_regulator_ops stpmic1_boost_ops = {
|
||||
.get_enable = stpmic1_boost_get_enable,
|
||||
.set_enable = stpmic1_boost_set_enable,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmic1_boost) = {
|
||||
.name = "stpmic1_boost",
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &stpmic1_boost_ops,
|
||||
.probe = stpmic1_boost_probe,
|
||||
};
|
||||
|
||||
/*
|
||||
* USB power switch
|
||||
*/
|
||||
|
||||
static int stpmic1_pwr_sw_get_enable(struct udevice *dev)
|
||||
{
|
||||
uint mask = 1 << dev->driver_data;
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMIC1_BST_SW_CR);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
return ret & mask ? true : false;
|
||||
}
|
||||
|
||||
static int stpmic1_pwr_sw_set_enable(struct udevice *dev, bool enable)
|
||||
{
|
||||
uint mask = 1 << dev->driver_data;
|
||||
int delay = enable ? STPMIC1_DEFAULT_START_UP_DELAY_MS :
|
||||
STPMIC1_DEFAULT_STOP_DELAY_MS;
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMIC1_BST_SW_CR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* if regulator is already in the wanted state, nothing to do */
|
||||
if (!!(ret & mask) == enable)
|
||||
return 0;
|
||||
|
||||
/* Boost management */
|
||||
if (enable && !(ret & STPMIC1_BST_ON)) {
|
||||
pmic_clrsetbits(dev->parent, STPMIC1_BST_SW_CR,
|
||||
STPMIC1_BST_ON, STPMIC1_BST_ON);
|
||||
mdelay(STPMIC1_USB_BOOST_START_UP_DELAY_MS);
|
||||
} else if (!enable && ret & STPMIC1_BST_ON &&
|
||||
(ret & STPMIC1_PWR_SW_ON) != STPMIC1_PWR_SW_ON) {
|
||||
pmic_clrsetbits(dev->parent, STPMIC1_BST_SW_CR,
|
||||
STPMIC1_BST_ON, 0);
|
||||
}
|
||||
|
||||
ret = pmic_clrsetbits(dev->parent, STPMIC1_BST_SW_CR,
|
||||
mask, enable ? mask : 0);
|
||||
mdelay(delay);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmic1_pwr_sw_probe(struct udevice *dev)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
|
||||
if (!dev->driver_data || dev->driver_data > STPMIC1_MAX_PWR_SW)
|
||||
return -EINVAL;
|
||||
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
|
||||
uc_pdata->type = REGULATOR_TYPE_FIXED;
|
||||
uc_pdata->mode_count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_regulator_ops stpmic1_pwr_sw_ops = {
|
||||
.get_enable = stpmic1_pwr_sw_get_enable,
|
||||
.set_enable = stpmic1_pwr_sw_set_enable,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmic1_pwr_sw) = {
|
||||
.name = "stpmic1_pwr_sw",
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &stpmic1_pwr_sw_ops,
|
||||
.probe = stpmic1_pwr_sw_probe,
|
||||
};
|
|
@ -1,671 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
||||
* Author: Christophe Kerello <christophe.kerello@st.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/stpmu1.h>
|
||||
|
||||
struct stpmu1_range {
|
||||
int min_uv;
|
||||
int min_sel;
|
||||
int max_sel;
|
||||
int step;
|
||||
};
|
||||
|
||||
struct stpmu1_output_range {
|
||||
const struct stpmu1_range *ranges;
|
||||
int nbranges;
|
||||
};
|
||||
|
||||
#define STPMU1_MODE(_id, _val, _name) { \
|
||||
.id = _id, \
|
||||
.register_value = _val, \
|
||||
.name = _name, \
|
||||
}
|
||||
|
||||
#define STPMU1_RANGE(_min_uv, _min_sel, _max_sel, _step) { \
|
||||
.min_uv = _min_uv, \
|
||||
.min_sel = _min_sel, \
|
||||
.max_sel = _max_sel, \
|
||||
.step = _step, \
|
||||
}
|
||||
|
||||
#define STPMU1_OUTPUT_RANGE(_ranges, _nbranges) { \
|
||||
.ranges = _ranges, \
|
||||
.nbranges = _nbranges, \
|
||||
}
|
||||
|
||||
static int stpmu1_output_find_uv(int sel,
|
||||
const struct stpmu1_output_range *output_range)
|
||||
{
|
||||
const struct stpmu1_range *range;
|
||||
int i;
|
||||
|
||||
for (i = 0, range = output_range->ranges;
|
||||
i < output_range->nbranges; i++, range++) {
|
||||
if (sel >= range->min_sel && sel <= range->max_sel)
|
||||
return range->min_uv +
|
||||
(sel - range->min_sel) * range->step;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int stpmu1_output_find_sel(int uv,
|
||||
const struct stpmu1_output_range *output_range)
|
||||
{
|
||||
const struct stpmu1_range *range;
|
||||
int i;
|
||||
|
||||
for (i = 0, range = output_range->ranges;
|
||||
i < output_range->nbranges; i++, range++) {
|
||||
if (uv == range->min_uv && !range->step)
|
||||
return range->min_sel;
|
||||
|
||||
if (uv >= range->min_uv &&
|
||||
uv <= range->min_uv +
|
||||
(range->max_sel - range->min_sel) * range->step)
|
||||
return range->min_sel +
|
||||
(uv - range->min_uv) / range->step;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* BUCK regulators
|
||||
*/
|
||||
|
||||
static const struct stpmu1_range buck1_ranges[] = {
|
||||
STPMU1_RANGE(600000, 0, 30, 25000),
|
||||
STPMU1_RANGE(1350000, 31, 63, 0),
|
||||
};
|
||||
|
||||
static const struct stpmu1_range buck2_ranges[] = {
|
||||
STPMU1_RANGE(1000000, 0, 17, 0),
|
||||
STPMU1_RANGE(1050000, 18, 19, 0),
|
||||
STPMU1_RANGE(1100000, 20, 21, 0),
|
||||
STPMU1_RANGE(1150000, 22, 23, 0),
|
||||
STPMU1_RANGE(1200000, 24, 25, 0),
|
||||
STPMU1_RANGE(1250000, 26, 27, 0),
|
||||
STPMU1_RANGE(1300000, 28, 29, 0),
|
||||
STPMU1_RANGE(1350000, 30, 31, 0),
|
||||
STPMU1_RANGE(1400000, 32, 33, 0),
|
||||
STPMU1_RANGE(1450000, 34, 35, 0),
|
||||
STPMU1_RANGE(1500000, 36, 63, 0),
|
||||
};
|
||||
|
||||
static const struct stpmu1_range buck3_ranges[] = {
|
||||
STPMU1_RANGE(1000000, 0, 19, 0),
|
||||
STPMU1_RANGE(1100000, 20, 23, 0),
|
||||
STPMU1_RANGE(1200000, 24, 27, 0),
|
||||
STPMU1_RANGE(1300000, 28, 31, 0),
|
||||
STPMU1_RANGE(1400000, 32, 35, 0),
|
||||
STPMU1_RANGE(1500000, 36, 55, 100000),
|
||||
STPMU1_RANGE(3400000, 56, 63, 0),
|
||||
};
|
||||
|
||||
static const struct stpmu1_range buck4_ranges[] = {
|
||||
STPMU1_RANGE(600000, 0, 27, 25000),
|
||||
STPMU1_RANGE(1300000, 28, 29, 0),
|
||||
STPMU1_RANGE(1350000, 30, 31, 0),
|
||||
STPMU1_RANGE(1400000, 32, 33, 0),
|
||||
STPMU1_RANGE(1450000, 34, 35, 0),
|
||||
STPMU1_RANGE(1500000, 36, 60, 100000),
|
||||
STPMU1_RANGE(3900000, 61, 63, 0),
|
||||
};
|
||||
|
||||
/* BUCK: 1,2,3,4 - voltage ranges */
|
||||
static const struct stpmu1_output_range buck_voltage_range[] = {
|
||||
STPMU1_OUTPUT_RANGE(buck1_ranges, ARRAY_SIZE(buck1_ranges)),
|
||||
STPMU1_OUTPUT_RANGE(buck2_ranges, ARRAY_SIZE(buck2_ranges)),
|
||||
STPMU1_OUTPUT_RANGE(buck3_ranges, ARRAY_SIZE(buck3_ranges)),
|
||||
STPMU1_OUTPUT_RANGE(buck4_ranges, ARRAY_SIZE(buck4_ranges)),
|
||||
};
|
||||
|
||||
/* BUCK modes */
|
||||
static const struct dm_regulator_mode buck_modes[] = {
|
||||
STPMU1_MODE(STPMU1_BUCK_MODE_HP, STPMU1_BUCK_MODE_HP, "HP"),
|
||||
STPMU1_MODE(STPMU1_BUCK_MODE_LP, STPMU1_BUCK_MODE_LP, "LP"),
|
||||
};
|
||||
|
||||
static int stpmu1_buck_get_uv(struct udevice *dev, int buck)
|
||||
{
|
||||
int sel;
|
||||
|
||||
sel = pmic_reg_read(dev, STPMU1_BUCKX_CTRL_REG(buck));
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
sel &= STPMU1_BUCK_OUTPUT_MASK;
|
||||
sel >>= STPMU1_BUCK_OUTPUT_SHIFT;
|
||||
|
||||
return stpmu1_output_find_uv(sel, &buck_voltage_range[buck]);
|
||||
}
|
||||
|
||||
static int stpmu1_buck_get_value(struct udevice *dev)
|
||||
{
|
||||
return stpmu1_buck_get_uv(dev->parent, dev->driver_data - 1);
|
||||
}
|
||||
|
||||
static int stpmu1_buck_set_value(struct udevice *dev, int uv)
|
||||
{
|
||||
int sel, buck = dev->driver_data - 1;
|
||||
|
||||
sel = stpmu1_output_find_sel(uv, &buck_voltage_range[buck]);
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
return pmic_clrsetbits(dev->parent,
|
||||
STPMU1_BUCKX_CTRL_REG(buck),
|
||||
STPMU1_BUCK_OUTPUT_MASK,
|
||||
sel << STPMU1_BUCK_OUTPUT_SHIFT);
|
||||
}
|
||||
|
||||
static int stpmu1_buck_get_enable(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent,
|
||||
STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1));
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
return ret & STPMU1_BUCK_EN ? true : false;
|
||||
}
|
||||
|
||||
static int stpmu1_buck_set_enable(struct udevice *dev, bool enable)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
int delay = enable ? STPMU1_DEFAULT_START_UP_DELAY_MS :
|
||||
STPMU1_DEFAULT_STOP_DELAY_MS;
|
||||
int ret, uv;
|
||||
|
||||
/* if regulator is already in the wanted state, nothing to do */
|
||||
if (stpmu1_buck_get_enable(dev) == enable)
|
||||
return 0;
|
||||
|
||||
if (enable) {
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
uv = stpmu1_buck_get_value(dev);
|
||||
if ((uv < uc_pdata->min_uV) || (uv > uc_pdata->max_uV))
|
||||
stpmu1_buck_set_value(dev, uc_pdata->min_uV);
|
||||
}
|
||||
|
||||
ret = pmic_clrsetbits(dev->parent,
|
||||
STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1),
|
||||
STPMU1_BUCK_EN, enable ? STPMU1_BUCK_EN : 0);
|
||||
mdelay(delay);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmu1_buck_get_mode(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent,
|
||||
STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ret & STPMU1_BUCK_MODE ? STPMU1_BUCK_MODE_LP :
|
||||
STPMU1_BUCK_MODE_HP;
|
||||
}
|
||||
|
||||
static int stpmu1_buck_set_mode(struct udevice *dev, int mode)
|
||||
{
|
||||
return pmic_clrsetbits(dev->parent,
|
||||
STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1),
|
||||
STPMU1_BUCK_MODE,
|
||||
mode ? STPMU1_BUCK_MODE : 0);
|
||||
}
|
||||
|
||||
static int stpmu1_buck_probe(struct udevice *dev)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
|
||||
if (!dev->driver_data || dev->driver_data > STPMU1_MAX_BUCK)
|
||||
return -EINVAL;
|
||||
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
|
||||
uc_pdata->type = REGULATOR_TYPE_BUCK;
|
||||
uc_pdata->mode = (struct dm_regulator_mode *)buck_modes;
|
||||
uc_pdata->mode_count = ARRAY_SIZE(buck_modes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_regulator_ops stpmu1_buck_ops = {
|
||||
.get_value = stpmu1_buck_get_value,
|
||||
.set_value = stpmu1_buck_set_value,
|
||||
.get_enable = stpmu1_buck_get_enable,
|
||||
.set_enable = stpmu1_buck_set_enable,
|
||||
.get_mode = stpmu1_buck_get_mode,
|
||||
.set_mode = stpmu1_buck_set_mode,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmu1_buck) = {
|
||||
.name = "stpmu1_buck",
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &stpmu1_buck_ops,
|
||||
.probe = stpmu1_buck_probe,
|
||||
};
|
||||
|
||||
/*
|
||||
* LDO regulators
|
||||
*/
|
||||
|
||||
static const struct stpmu1_range ldo12_ranges[] = {
|
||||
STPMU1_RANGE(1700000, 0, 7, 0),
|
||||
STPMU1_RANGE(1700000, 8, 24, 100000),
|
||||
STPMU1_RANGE(3300000, 25, 31, 0),
|
||||
};
|
||||
|
||||
static const struct stpmu1_range ldo3_ranges[] = {
|
||||
STPMU1_RANGE(1700000, 0, 7, 0),
|
||||
STPMU1_RANGE(1700000, 8, 24, 100000),
|
||||
STPMU1_RANGE(3300000, 25, 30, 0),
|
||||
/* Sel 31 is special case when LDO3 is in mode sync_source (BUCK2/2) */
|
||||
};
|
||||
|
||||
static const struct stpmu1_range ldo5_ranges[] = {
|
||||
STPMU1_RANGE(1700000, 0, 7, 0),
|
||||
STPMU1_RANGE(1700000, 8, 30, 100000),
|
||||
STPMU1_RANGE(3900000, 31, 31, 0),
|
||||
};
|
||||
|
||||
static const struct stpmu1_range ldo6_ranges[] = {
|
||||
STPMU1_RANGE(900000, 0, 24, 100000),
|
||||
STPMU1_RANGE(3300000, 25, 31, 0),
|
||||
};
|
||||
|
||||
/* LDO: 1,2,3,4,5,6 - voltage ranges */
|
||||
static const struct stpmu1_output_range ldo_voltage_range[] = {
|
||||
STPMU1_OUTPUT_RANGE(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)),
|
||||
STPMU1_OUTPUT_RANGE(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)),
|
||||
STPMU1_OUTPUT_RANGE(ldo3_ranges, ARRAY_SIZE(ldo3_ranges)),
|
||||
STPMU1_OUTPUT_RANGE(NULL, 0),
|
||||
STPMU1_OUTPUT_RANGE(ldo5_ranges, ARRAY_SIZE(ldo5_ranges)),
|
||||
STPMU1_OUTPUT_RANGE(ldo6_ranges, ARRAY_SIZE(ldo6_ranges)),
|
||||
};
|
||||
|
||||
/* LDO modes */
|
||||
static const struct dm_regulator_mode ldo_modes[] = {
|
||||
STPMU1_MODE(STPMU1_LDO_MODE_NORMAL,
|
||||
STPMU1_LDO_MODE_NORMAL, "NORMAL"),
|
||||
STPMU1_MODE(STPMU1_LDO_MODE_BYPASS,
|
||||
STPMU1_LDO_MODE_BYPASS, "BYPASS"),
|
||||
STPMU1_MODE(STPMU1_LDO_MODE_SINK_SOURCE,
|
||||
STPMU1_LDO_MODE_SINK_SOURCE, "SINK SOURCE"),
|
||||
};
|
||||
|
||||
static int stpmu1_ldo_get_value(struct udevice *dev)
|
||||
{
|
||||
int sel, ldo = dev->driver_data - 1;
|
||||
|
||||
sel = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo));
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
/* ldo4 => 3,3V */
|
||||
if (ldo == STPMU1_LDO4)
|
||||
return STPMU1_LDO4_UV;
|
||||
|
||||
sel &= STPMU1_LDO12356_OUTPUT_MASK;
|
||||
sel >>= STPMU1_LDO12356_OUTPUT_SHIFT;
|
||||
|
||||
/* ldo3, sel = 31 => BUCK2/2 */
|
||||
if (ldo == STPMU1_LDO3 && sel == STPMU1_LDO3_DDR_SEL)
|
||||
return stpmu1_buck_get_uv(dev->parent, STPMU1_BUCK2) / 2;
|
||||
|
||||
return stpmu1_output_find_uv(sel, &ldo_voltage_range[ldo]);
|
||||
}
|
||||
|
||||
static int stpmu1_ldo_set_value(struct udevice *dev, int uv)
|
||||
{
|
||||
int sel, ldo = dev->driver_data - 1;
|
||||
|
||||
/* ldo4 => not possible */
|
||||
if (ldo == STPMU1_LDO4)
|
||||
return -EINVAL;
|
||||
|
||||
sel = stpmu1_output_find_sel(uv, &ldo_voltage_range[ldo]);
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
return pmic_clrsetbits(dev->parent,
|
||||
STPMU1_LDOX_CTRL_REG(ldo),
|
||||
STPMU1_LDO12356_OUTPUT_MASK,
|
||||
sel << STPMU1_LDO12356_OUTPUT_SHIFT);
|
||||
}
|
||||
|
||||
static int stpmu1_ldo_get_enable(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent,
|
||||
STPMU1_LDOX_CTRL_REG(dev->driver_data - 1));
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
return ret & STPMU1_LDO_EN ? true : false;
|
||||
}
|
||||
|
||||
static int stpmu1_ldo_set_enable(struct udevice *dev, bool enable)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
int delay = enable ? STPMU1_DEFAULT_START_UP_DELAY_MS :
|
||||
STPMU1_DEFAULT_STOP_DELAY_MS;
|
||||
int ret, uv;
|
||||
|
||||
/* if regulator is already in the wanted state, nothing to do */
|
||||
if (stpmu1_ldo_get_enable(dev) == enable)
|
||||
return 0;
|
||||
|
||||
if (enable) {
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
uv = stpmu1_ldo_get_value(dev);
|
||||
if ((uv < uc_pdata->min_uV) || (uv > uc_pdata->max_uV))
|
||||
stpmu1_ldo_set_value(dev, uc_pdata->min_uV);
|
||||
}
|
||||
|
||||
ret = pmic_clrsetbits(dev->parent,
|
||||
STPMU1_LDOX_CTRL_REG(dev->driver_data - 1),
|
||||
STPMU1_LDO_EN, enable ? STPMU1_LDO_EN : 0);
|
||||
mdelay(delay);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmu1_ldo_get_mode(struct udevice *dev)
|
||||
{
|
||||
int ret, ldo = dev->driver_data - 1;
|
||||
|
||||
if (ldo != STPMU1_LDO3)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret & STPMU1_LDO3_MODE)
|
||||
return STPMU1_LDO_MODE_BYPASS;
|
||||
|
||||
ret &= STPMU1_LDO12356_OUTPUT_MASK;
|
||||
ret >>= STPMU1_LDO12356_OUTPUT_SHIFT;
|
||||
|
||||
return ret == STPMU1_LDO3_DDR_SEL ? STPMU1_LDO_MODE_SINK_SOURCE :
|
||||
STPMU1_LDO_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static int stpmu1_ldo_set_mode(struct udevice *dev, int mode)
|
||||
{
|
||||
int ret, ldo = dev->driver_data - 1;
|
||||
|
||||
if (ldo != STPMU1_LDO3)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (mode) {
|
||||
case STPMU1_LDO_MODE_SINK_SOURCE:
|
||||
ret &= ~STPMU1_LDO12356_OUTPUT_MASK;
|
||||
ret |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT;
|
||||
case STPMU1_LDO_MODE_NORMAL:
|
||||
ret &= ~STPMU1_LDO3_MODE;
|
||||
break;
|
||||
case STPMU1_LDO_MODE_BYPASS:
|
||||
ret |= STPMU1_LDO3_MODE;
|
||||
break;
|
||||
}
|
||||
|
||||
return pmic_reg_write(dev->parent, STPMU1_LDOX_CTRL_REG(ldo), ret);
|
||||
}
|
||||
|
||||
static int stpmu1_ldo_probe(struct udevice *dev)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
|
||||
if (!dev->driver_data || dev->driver_data > STPMU1_MAX_LDO)
|
||||
return -EINVAL;
|
||||
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
|
||||
uc_pdata->type = REGULATOR_TYPE_LDO;
|
||||
if (dev->driver_data - 1 == STPMU1_LDO3) {
|
||||
uc_pdata->mode = (struct dm_regulator_mode *)ldo_modes;
|
||||
uc_pdata->mode_count = ARRAY_SIZE(ldo_modes);
|
||||
} else {
|
||||
uc_pdata->mode_count = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_regulator_ops stpmu1_ldo_ops = {
|
||||
.get_value = stpmu1_ldo_get_value,
|
||||
.set_value = stpmu1_ldo_set_value,
|
||||
.get_enable = stpmu1_ldo_get_enable,
|
||||
.set_enable = stpmu1_ldo_set_enable,
|
||||
.get_mode = stpmu1_ldo_get_mode,
|
||||
.set_mode = stpmu1_ldo_set_mode,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmu1_ldo) = {
|
||||
.name = "stpmu1_ldo",
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &stpmu1_ldo_ops,
|
||||
.probe = stpmu1_ldo_probe,
|
||||
};
|
||||
|
||||
/*
|
||||
* VREF DDR regulator
|
||||
*/
|
||||
|
||||
static int stpmu1_vref_ddr_get_value(struct udevice *dev)
|
||||
{
|
||||
/* BUCK2/2 */
|
||||
return stpmu1_buck_get_uv(dev->parent, STPMU1_BUCK2) / 2;
|
||||
}
|
||||
|
||||
static int stpmu1_vref_ddr_get_enable(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMU1_VREF_CTRL_REG);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
return ret & STPMU1_VREF_EN ? true : false;
|
||||
}
|
||||
|
||||
static int stpmu1_vref_ddr_set_enable(struct udevice *dev, bool enable)
|
||||
{
|
||||
int delay = enable ? STPMU1_DEFAULT_START_UP_DELAY_MS :
|
||||
STPMU1_DEFAULT_STOP_DELAY_MS;
|
||||
int ret;
|
||||
|
||||
/* if regulator is already in the wanted state, nothing to do */
|
||||
if (stpmu1_vref_ddr_get_enable(dev) == enable)
|
||||
return 0;
|
||||
|
||||
ret = pmic_clrsetbits(dev->parent, STPMU1_VREF_CTRL_REG,
|
||||
STPMU1_VREF_EN, enable ? STPMU1_VREF_EN : 0);
|
||||
mdelay(delay);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmu1_vref_ddr_probe(struct udevice *dev)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
|
||||
uc_pdata->type = REGULATOR_TYPE_FIXED;
|
||||
uc_pdata->mode_count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_regulator_ops stpmu1_vref_ddr_ops = {
|
||||
.get_value = stpmu1_vref_ddr_get_value,
|
||||
.get_enable = stpmu1_vref_ddr_get_enable,
|
||||
.set_enable = stpmu1_vref_ddr_set_enable,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmu1_vref_ddr) = {
|
||||
.name = "stpmu1_vref_ddr",
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &stpmu1_vref_ddr_ops,
|
||||
.probe = stpmu1_vref_ddr_probe,
|
||||
};
|
||||
|
||||
/*
|
||||
* BOOST regulator
|
||||
*/
|
||||
|
||||
static int stpmu1_boost_get_enable(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
return ret & STPMU1_USB_BOOST_EN ? true : false;
|
||||
}
|
||||
|
||||
static int stpmu1_boost_set_enable(struct udevice *dev, bool enable)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!enable && ret & STPMU1_USB_PWR_SW_EN)
|
||||
return -EINVAL;
|
||||
|
||||
/* if regulator is already in the wanted state, nothing to do */
|
||||
if (!!(ret & STPMU1_USB_BOOST_EN) == enable)
|
||||
return 0;
|
||||
|
||||
ret = pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG,
|
||||
STPMU1_USB_BOOST_EN,
|
||||
enable ? STPMU1_USB_BOOST_EN : 0);
|
||||
if (enable)
|
||||
mdelay(STPMU1_USB_BOOST_START_UP_DELAY_MS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmu1_boost_probe(struct udevice *dev)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
|
||||
uc_pdata->type = REGULATOR_TYPE_FIXED;
|
||||
uc_pdata->mode_count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_regulator_ops stpmu1_boost_ops = {
|
||||
.get_enable = stpmu1_boost_get_enable,
|
||||
.set_enable = stpmu1_boost_set_enable,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmu1_boost) = {
|
||||
.name = "stpmu1_boost",
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &stpmu1_boost_ops,
|
||||
.probe = stpmu1_boost_probe,
|
||||
};
|
||||
|
||||
/*
|
||||
* USB power switch
|
||||
*/
|
||||
|
||||
static int stpmu1_pwr_sw_get_enable(struct udevice *dev)
|
||||
{
|
||||
uint mask = 1 << dev->driver_data;
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
return ret & mask ? true : false;
|
||||
}
|
||||
|
||||
static int stpmu1_pwr_sw_set_enable(struct udevice *dev, bool enable)
|
||||
{
|
||||
uint mask = 1 << dev->driver_data;
|
||||
int delay = enable ? STPMU1_DEFAULT_START_UP_DELAY_MS :
|
||||
STPMU1_DEFAULT_STOP_DELAY_MS;
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* if regulator is already in the wanted state, nothing to do */
|
||||
if (!!(ret & mask) == enable)
|
||||
return 0;
|
||||
|
||||
/* Boost management */
|
||||
if (enable && !(ret & STPMU1_USB_BOOST_EN)) {
|
||||
pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG,
|
||||
STPMU1_USB_BOOST_EN, STPMU1_USB_BOOST_EN);
|
||||
mdelay(STPMU1_USB_BOOST_START_UP_DELAY_MS);
|
||||
} else if (!enable && ret & STPMU1_USB_BOOST_EN &&
|
||||
(ret & STPMU1_USB_PWR_SW_EN) != STPMU1_USB_PWR_SW_EN) {
|
||||
pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG,
|
||||
STPMU1_USB_BOOST_EN, 0);
|
||||
}
|
||||
|
||||
ret = pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG,
|
||||
mask, enable ? mask : 0);
|
||||
mdelay(delay);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmu1_pwr_sw_probe(struct udevice *dev)
|
||||
{
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
|
||||
if (!dev->driver_data || dev->driver_data > STPMU1_MAX_PWR_SW)
|
||||
return -EINVAL;
|
||||
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
|
||||
uc_pdata->type = REGULATOR_TYPE_FIXED;
|
||||
uc_pdata->mode_count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_regulator_ops stpmu1_pwr_sw_ops = {
|
||||
.get_enable = stpmu1_pwr_sw_get_enable,
|
||||
.set_enable = stpmu1_pwr_sw_set_enable,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmu1_pwr_sw) = {
|
||||
.name = "stpmu1_pwr_sw",
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &stpmu1_pwr_sw_ops,
|
||||
.probe = stpmu1_pwr_sw_probe,
|
||||
};
|
|
@ -157,7 +157,8 @@ static int stm32mp1_ddr_probe(struct udevice *dev)
|
|||
|
||||
priv->info.base = STM32_DDR_BASE;
|
||||
|
||||
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
|
||||
#if !defined(CONFIG_STM32MP1_TRUSTED) && \
|
||||
(!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
|
||||
priv->info.size = 0;
|
||||
return stm32mp1_ddr_setup(dev);
|
||||
#else
|
||||
|
|
|
@ -222,8 +222,7 @@ config SPI_SUNXI
|
|||
|
||||
config STM32_QSPI
|
||||
bool "STM32F7 QSPI driver"
|
||||
depends on STM32F7
|
||||
imply SPI_FLASH_BAR
|
||||
depends on STM32F7 || ARCH_STM32MP
|
||||
help
|
||||
Enable the STM32F7 Quad-SPI (QSPI) driver. This driver can be
|
||||
used to access the SPI NOR flash chips on platforms embedding
|
||||
|
|
|
@ -9,15 +9,11 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <reset.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/stm32.h>
|
||||
#include <spi-mem.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
struct stm32_qspi_regs {
|
||||
u32 cr; /* 0x00 */
|
||||
|
@ -45,8 +41,7 @@ struct stm32_qspi_regs {
|
|||
#define STM32_QSPI_CR_SSHIFT BIT(4)
|
||||
#define STM32_QSPI_CR_DFM BIT(6)
|
||||
#define STM32_QSPI_CR_FSEL BIT(7)
|
||||
#define STM32_QSPI_CR_FTHRES_MASK GENMASK(4, 0)
|
||||
#define STM32_QSPI_CR_FTHRES_SHIFT (8)
|
||||
#define STM32_QSPI_CR_FTHRES_SHIFT 8
|
||||
#define STM32_QSPI_CR_TEIE BIT(16)
|
||||
#define STM32_QSPI_CR_TCIE BIT(17)
|
||||
#define STM32_QSPI_CR_FTIE BIT(18)
|
||||
|
@ -55,16 +50,16 @@ struct stm32_qspi_regs {
|
|||
#define STM32_QSPI_CR_APMS BIT(22)
|
||||
#define STM32_QSPI_CR_PMM BIT(23)
|
||||
#define STM32_QSPI_CR_PRESCALER_MASK GENMASK(7, 0)
|
||||
#define STM32_QSPI_CR_PRESCALER_SHIFT (24)
|
||||
#define STM32_QSPI_CR_PRESCALER_SHIFT 24
|
||||
|
||||
/*
|
||||
* QUADSPI device configuration register
|
||||
*/
|
||||
#define STM32_QSPI_DCR_CKMODE BIT(0)
|
||||
#define STM32_QSPI_DCR_CSHT_MASK GENMASK(2, 0)
|
||||
#define STM32_QSPI_DCR_CSHT_SHIFT (8)
|
||||
#define STM32_QSPI_DCR_CSHT_SHIFT 8
|
||||
#define STM32_QSPI_DCR_FSIZE_MASK GENMASK(4, 0)
|
||||
#define STM32_QSPI_DCR_FSIZE_SHIFT (16)
|
||||
#define STM32_QSPI_DCR_FSIZE_SHIFT 16
|
||||
|
||||
/*
|
||||
* QUADSPI status register
|
||||
|
@ -75,8 +70,6 @@ struct stm32_qspi_regs {
|
|||
#define STM32_QSPI_SR_SMF BIT(3)
|
||||
#define STM32_QSPI_SR_TOF BIT(4)
|
||||
#define STM32_QSPI_SR_BUSY BIT(5)
|
||||
#define STM32_QSPI_SR_FLEVEL_MASK GENMASK(5, 0)
|
||||
#define STM32_QSPI_SR_FLEVEL_SHIFT (8)
|
||||
|
||||
/*
|
||||
* QUADSPI flag clear register
|
||||
|
@ -92,388 +85,276 @@ struct stm32_qspi_regs {
|
|||
#define STM32_QSPI_CCR_DDRM BIT(31)
|
||||
#define STM32_QSPI_CCR_DHHC BIT(30)
|
||||
#define STM32_QSPI_CCR_SIOO BIT(28)
|
||||
#define STM32_QSPI_CCR_FMODE_SHIFT (26)
|
||||
#define STM32_QSPI_CCR_DMODE_SHIFT (24)
|
||||
#define STM32_QSPI_CCR_DCYC_SHIFT (18)
|
||||
#define STM32_QSPI_CCR_DCYC_MASK GENMASK(4, 0)
|
||||
#define STM32_QSPI_CCR_ABSIZE_SHIFT (16)
|
||||
#define STM32_QSPI_CCR_ABMODE_SHIFT (14)
|
||||
#define STM32_QSPI_CCR_ADSIZE_SHIFT (12)
|
||||
#define STM32_QSPI_CCR_ADMODE_SHIFT (10)
|
||||
#define STM32_QSPI_CCR_IMODE_SHIFT (8)
|
||||
#define STM32_QSPI_CCR_INSTRUCTION_MASK GENMASK(7, 0)
|
||||
#define STM32_QSPI_CCR_FMODE_SHIFT 26
|
||||
#define STM32_QSPI_CCR_DMODE_SHIFT 24
|
||||
#define STM32_QSPI_CCR_DCYC_SHIFT 18
|
||||
#define STM32_QSPI_CCR_ABSIZE_SHIFT 16
|
||||
#define STM32_QSPI_CCR_ABMODE_SHIFT 14
|
||||
#define STM32_QSPI_CCR_ADSIZE_SHIFT 12
|
||||
#define STM32_QSPI_CCR_ADMODE_SHIFT 10
|
||||
#define STM32_QSPI_CCR_IMODE_SHIFT 8
|
||||
|
||||
enum STM32_QSPI_CCR_IMODE {
|
||||
STM32_QSPI_CCR_IMODE_NONE = 0,
|
||||
STM32_QSPI_CCR_IMODE_ONE_LINE = 1,
|
||||
STM32_QSPI_CCR_IMODE_TWO_LINE = 2,
|
||||
STM32_QSPI_CCR_IMODE_FOUR_LINE = 3,
|
||||
};
|
||||
#define STM32_QSPI_CCR_IND_WRITE 0
|
||||
#define STM32_QSPI_CCR_IND_READ 1
|
||||
#define STM32_QSPI_CCR_MEM_MAP 3
|
||||
|
||||
enum STM32_QSPI_CCR_ADMODE {
|
||||
STM32_QSPI_CCR_ADMODE_NONE = 0,
|
||||
STM32_QSPI_CCR_ADMODE_ONE_LINE = 1,
|
||||
STM32_QSPI_CCR_ADMODE_TWO_LINE = 2,
|
||||
STM32_QSPI_CCR_ADMODE_FOUR_LINE = 3,
|
||||
};
|
||||
#define STM32_QSPI_MAX_MMAP_SZ SZ_256M
|
||||
#define STM32_QSPI_MAX_CHIP 2
|
||||
|
||||
enum STM32_QSPI_CCR_ADSIZE {
|
||||
STM32_QSPI_CCR_ADSIZE_8BIT = 0,
|
||||
STM32_QSPI_CCR_ADSIZE_16BIT = 1,
|
||||
STM32_QSPI_CCR_ADSIZE_24BIT = 2,
|
||||
STM32_QSPI_CCR_ADSIZE_32BIT = 3,
|
||||
};
|
||||
#define STM32_QSPI_FIFO_TIMEOUT_US 30000
|
||||
#define STM32_QSPI_CMD_TIMEOUT_US 1000000
|
||||
#define STM32_BUSY_TIMEOUT_US 100000
|
||||
#define STM32_ABT_TIMEOUT_US 100000
|
||||
|
||||
enum STM32_QSPI_CCR_ABMODE {
|
||||
STM32_QSPI_CCR_ABMODE_NONE = 0,
|
||||
STM32_QSPI_CCR_ABMODE_ONE_LINE = 1,
|
||||
STM32_QSPI_CCR_ABMODE_TWO_LINE = 2,
|
||||
STM32_QSPI_CCR_ABMODE_FOUR_LINE = 3,
|
||||
};
|
||||
|
||||
enum STM32_QSPI_CCR_ABSIZE {
|
||||
STM32_QSPI_CCR_ABSIZE_8BIT = 0,
|
||||
STM32_QSPI_CCR_ABSIZE_16BIT = 1,
|
||||
STM32_QSPI_CCR_ABSIZE_24BIT = 2,
|
||||
STM32_QSPI_CCR_ABSIZE_32BIT = 3,
|
||||
};
|
||||
|
||||
enum STM32_QSPI_CCR_DMODE {
|
||||
STM32_QSPI_CCR_DMODE_NONE = 0,
|
||||
STM32_QSPI_CCR_DMODE_ONE_LINE = 1,
|
||||
STM32_QSPI_CCR_DMODE_TWO_LINE = 2,
|
||||
STM32_QSPI_CCR_DMODE_FOUR_LINE = 3,
|
||||
};
|
||||
|
||||
enum STM32_QSPI_CCR_FMODE {
|
||||
STM32_QSPI_CCR_IND_WRITE = 0,
|
||||
STM32_QSPI_CCR_IND_READ = 1,
|
||||
STM32_QSPI_CCR_AUTO_POLL = 2,
|
||||
STM32_QSPI_CCR_MEM_MAP = 3,
|
||||
};
|
||||
|
||||
/* default SCK frequency, unit: HZ */
|
||||
#define STM32_QSPI_DEFAULT_SCK_FREQ 108000000
|
||||
|
||||
#define STM32_MAX_NORCHIP 2
|
||||
|
||||
struct stm32_qspi_platdata {
|
||||
u32 base;
|
||||
u32 memory_map;
|
||||
u32 max_hz;
|
||||
struct stm32_qspi_flash {
|
||||
u32 cr;
|
||||
u32 dcr;
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
struct stm32_qspi_priv {
|
||||
struct stm32_qspi_regs *regs;
|
||||
struct stm32_qspi_flash flash[STM32_QSPI_MAX_CHIP];
|
||||
void __iomem *mm_base;
|
||||
resource_size_t mm_size;
|
||||
ulong clock_rate;
|
||||
u32 max_hz;
|
||||
u32 mode;
|
||||
|
||||
u32 command;
|
||||
u32 address;
|
||||
u32 dummycycles;
|
||||
#define CMD_HAS_ADR BIT(24)
|
||||
#define CMD_HAS_DUMMY BIT(25)
|
||||
#define CMD_HAS_DATA BIT(26)
|
||||
int cs_used;
|
||||
};
|
||||
|
||||
static void _stm32_qspi_disable(struct stm32_qspi_priv *priv)
|
||||
static int _stm32_qspi_wait_for_not_busy(struct stm32_qspi_priv *priv)
|
||||
{
|
||||
clrbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN);
|
||||
}
|
||||
|
||||
static void _stm32_qspi_enable(struct stm32_qspi_priv *priv)
|
||||
{
|
||||
setbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN);
|
||||
}
|
||||
|
||||
static void _stm32_qspi_wait_for_not_busy(struct stm32_qspi_priv *priv)
|
||||
{
|
||||
while (readl(&priv->regs->sr) & STM32_QSPI_SR_BUSY)
|
||||
;
|
||||
}
|
||||
|
||||
static void _stm32_qspi_wait_for_complete(struct stm32_qspi_priv *priv)
|
||||
{
|
||||
while (!(readl(&priv->regs->sr) & STM32_QSPI_SR_TCF))
|
||||
;
|
||||
}
|
||||
|
||||
static void _stm32_qspi_wait_for_ftf(struct stm32_qspi_priv *priv)
|
||||
{
|
||||
while (!(readl(&priv->regs->sr) & STM32_QSPI_SR_FTF))
|
||||
;
|
||||
}
|
||||
|
||||
static void _stm32_qspi_set_flash_size(struct stm32_qspi_priv *priv, u32 size)
|
||||
{
|
||||
u32 fsize = fls(size) - 1;
|
||||
|
||||
clrsetbits_le32(&priv->regs->dcr,
|
||||
STM32_QSPI_DCR_FSIZE_MASK << STM32_QSPI_DCR_FSIZE_SHIFT,
|
||||
fsize << STM32_QSPI_DCR_FSIZE_SHIFT);
|
||||
}
|
||||
|
||||
static void _stm32_qspi_set_cs(struct stm32_qspi_priv *priv, unsigned int cs)
|
||||
{
|
||||
clrsetbits_le32(&priv->regs->cr, STM32_QSPI_CR_FSEL,
|
||||
cs ? STM32_QSPI_CR_FSEL : 0);
|
||||
}
|
||||
|
||||
static unsigned int _stm32_qspi_gen_ccr(struct stm32_qspi_priv *priv, u8 fmode)
|
||||
{
|
||||
unsigned int ccr_reg = 0;
|
||||
u8 imode, admode, dmode;
|
||||
u32 mode = priv->mode;
|
||||
u32 cmd = (priv->command & STM32_QSPI_CCR_INSTRUCTION_MASK);
|
||||
|
||||
imode = STM32_QSPI_CCR_IMODE_ONE_LINE;
|
||||
admode = STM32_QSPI_CCR_ADMODE_ONE_LINE;
|
||||
dmode = STM32_QSPI_CCR_DMODE_ONE_LINE;
|
||||
|
||||
if ((priv->command & CMD_HAS_ADR) && (priv->command & CMD_HAS_DATA)) {
|
||||
if (fmode == STM32_QSPI_CCR_IND_WRITE) {
|
||||
if (mode & SPI_TX_QUAD)
|
||||
dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE;
|
||||
else if (mode & SPI_TX_DUAL)
|
||||
dmode = STM32_QSPI_CCR_DMODE_TWO_LINE;
|
||||
} else if ((fmode == STM32_QSPI_CCR_MEM_MAP) ||
|
||||
(fmode == STM32_QSPI_CCR_IND_READ)) {
|
||||
if (mode & SPI_RX_QUAD)
|
||||
dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE;
|
||||
else if (mode & SPI_RX_DUAL)
|
||||
dmode = STM32_QSPI_CCR_DMODE_TWO_LINE;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->command & CMD_HAS_DATA)
|
||||
ccr_reg |= (dmode << STM32_QSPI_CCR_DMODE_SHIFT);
|
||||
|
||||
if (priv->command & CMD_HAS_DUMMY)
|
||||
ccr_reg |= ((priv->dummycycles & STM32_QSPI_CCR_DCYC_MASK)
|
||||
<< STM32_QSPI_CCR_DCYC_SHIFT);
|
||||
|
||||
if (priv->command & CMD_HAS_ADR) {
|
||||
ccr_reg |= (STM32_QSPI_CCR_ADSIZE_24BIT
|
||||
<< STM32_QSPI_CCR_ADSIZE_SHIFT);
|
||||
ccr_reg |= (admode << STM32_QSPI_CCR_ADMODE_SHIFT);
|
||||
}
|
||||
|
||||
ccr_reg |= (fmode << STM32_QSPI_CCR_FMODE_SHIFT);
|
||||
ccr_reg |= (imode << STM32_QSPI_CCR_IMODE_SHIFT);
|
||||
ccr_reg |= cmd;
|
||||
|
||||
return ccr_reg;
|
||||
}
|
||||
|
||||
static void _stm32_qspi_enable_mmap(struct stm32_qspi_priv *priv,
|
||||
struct spi_flash *flash)
|
||||
{
|
||||
unsigned int ccr_reg;
|
||||
|
||||
priv->command = flash->read_opcode | CMD_HAS_ADR | CMD_HAS_DATA
|
||||
| CMD_HAS_DUMMY;
|
||||
priv->dummycycles = flash->read_dummy;
|
||||
|
||||
ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_MEM_MAP);
|
||||
|
||||
_stm32_qspi_wait_for_not_busy(priv);
|
||||
|
||||
writel(ccr_reg, &priv->regs->ccr);
|
||||
|
||||
priv->dummycycles = 0;
|
||||
}
|
||||
|
||||
static void _stm32_qspi_disable_mmap(struct stm32_qspi_priv *priv)
|
||||
{
|
||||
setbits_le32(&priv->regs->cr, STM32_QSPI_CR_ABORT);
|
||||
}
|
||||
|
||||
static void _stm32_qspi_set_xfer_length(struct stm32_qspi_priv *priv,
|
||||
u32 length)
|
||||
{
|
||||
writel(length - 1, &priv->regs->dlr);
|
||||
}
|
||||
|
||||
static void _stm32_qspi_start_xfer(struct stm32_qspi_priv *priv, u32 cr_reg)
|
||||
{
|
||||
writel(cr_reg, &priv->regs->ccr);
|
||||
|
||||
if (priv->command & CMD_HAS_ADR)
|
||||
writel(priv->address, &priv->regs->ar);
|
||||
}
|
||||
|
||||
static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv,
|
||||
struct spi_flash *flash, unsigned int bitlen,
|
||||
const u8 *dout, u8 *din, unsigned long flags)
|
||||
{
|
||||
unsigned int words = bitlen / 8;
|
||||
u32 ccr_reg;
|
||||
int i;
|
||||
|
||||
if (flags & SPI_XFER_MMAP) {
|
||||
_stm32_qspi_enable_mmap(priv, flash);
|
||||
return 0;
|
||||
} else if (flags & SPI_XFER_MMAP_END) {
|
||||
_stm32_qspi_disable_mmap(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bitlen == 0)
|
||||
return -1;
|
||||
|
||||
if (bitlen % 8) {
|
||||
debug("spi_xfer: Non byte aligned SPI transfer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dout && din) {
|
||||
debug("spi_xfer: QSPI cannot have data in and data out set\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!dout && (flags & SPI_XFER_BEGIN)) {
|
||||
debug("spi_xfer: QSPI transfer must begin with command\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dout) {
|
||||
if (flags & SPI_XFER_BEGIN) {
|
||||
/* data is command */
|
||||
priv->command = dout[0] | CMD_HAS_DATA;
|
||||
if (words >= 4) {
|
||||
/* address is here too */
|
||||
priv->address = (dout[1] << 16) |
|
||||
(dout[2] << 8) | dout[3];
|
||||
priv->command |= CMD_HAS_ADR;
|
||||
}
|
||||
|
||||
if (words > 4) {
|
||||
/* rest is dummy bytes */
|
||||
priv->dummycycles = (words - 4) * 8;
|
||||
priv->command |= CMD_HAS_DUMMY;
|
||||
}
|
||||
|
||||
if (flags & SPI_XFER_END) {
|
||||
/* command without data */
|
||||
priv->command &= ~(CMD_HAS_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & SPI_XFER_END) {
|
||||
ccr_reg = _stm32_qspi_gen_ccr(priv,
|
||||
STM32_QSPI_CCR_IND_WRITE);
|
||||
|
||||
_stm32_qspi_wait_for_not_busy(priv);
|
||||
|
||||
if (priv->command & CMD_HAS_DATA)
|
||||
_stm32_qspi_set_xfer_length(priv, words);
|
||||
|
||||
_stm32_qspi_start_xfer(priv, ccr_reg);
|
||||
|
||||
debug("%s: write: ccr:0x%08x adr:0x%08x\n",
|
||||
__func__, priv->regs->ccr, priv->regs->ar);
|
||||
|
||||
if (priv->command & CMD_HAS_DATA) {
|
||||
_stm32_qspi_wait_for_ftf(priv);
|
||||
|
||||
debug("%s: words:%d data:", __func__, words);
|
||||
|
||||
i = 0;
|
||||
while (words > i) {
|
||||
writeb(dout[i], &priv->regs->dr);
|
||||
debug("%02x ", dout[i]);
|
||||
i++;
|
||||
}
|
||||
debug("\n");
|
||||
|
||||
_stm32_qspi_wait_for_complete(priv);
|
||||
} else {
|
||||
_stm32_qspi_wait_for_not_busy(priv);
|
||||
}
|
||||
}
|
||||
} else if (din) {
|
||||
ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_IND_READ);
|
||||
|
||||
_stm32_qspi_wait_for_not_busy(priv);
|
||||
|
||||
_stm32_qspi_set_xfer_length(priv, words);
|
||||
|
||||
_stm32_qspi_start_xfer(priv, ccr_reg);
|
||||
|
||||
debug("%s: read: ccr:0x%08x adr:0x%08x len:%d\n", __func__,
|
||||
priv->regs->ccr, priv->regs->ar, priv->regs->dlr);
|
||||
|
||||
debug("%s: data:", __func__);
|
||||
|
||||
i = 0;
|
||||
while (words > i) {
|
||||
din[i] = readb(&priv->regs->dr);
|
||||
debug("%02x ", din[i]);
|
||||
i++;
|
||||
}
|
||||
debug("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_qspi_ofdata_to_platdata(struct udevice *bus)
|
||||
{
|
||||
struct resource res_regs, res_mem;
|
||||
struct stm32_qspi_platdata *plat = bus->platdata;
|
||||
u32 sr;
|
||||
int ret;
|
||||
|
||||
ret = dev_read_resource_byname(bus, "qspi", &res_regs);
|
||||
ret = readl_poll_timeout(&priv->regs->sr, sr,
|
||||
!(sr & STM32_QSPI_SR_BUSY),
|
||||
STM32_BUSY_TIMEOUT_US);
|
||||
if (ret)
|
||||
pr_err("busy timeout (stat:%#x)\n", sr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _stm32_qspi_wait_cmd(struct stm32_qspi_priv *priv,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
u32 sr;
|
||||
int ret;
|
||||
|
||||
if (!op->data.nbytes)
|
||||
return _stm32_qspi_wait_for_not_busy(priv);
|
||||
|
||||
ret = readl_poll_timeout(&priv->regs->sr, sr,
|
||||
sr & STM32_QSPI_SR_TCF,
|
||||
STM32_QSPI_CMD_TIMEOUT_US);
|
||||
if (ret) {
|
||||
debug("Error: can't get regs base addresses(ret = %d)!\n", ret);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ret = dev_read_resource_byname(bus, "qspi_mm", &res_mem);
|
||||
if (ret) {
|
||||
debug("Error: can't get mmap base address(ret = %d)!\n", ret);
|
||||
return -ENOMEM;
|
||||
pr_err("cmd timeout (stat:%#x)\n", sr);
|
||||
} else if (readl(&priv->regs->sr) & STM32_QSPI_SR_TEF) {
|
||||
pr_err("transfer error (stat:%#x)\n", sr);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
plat->max_hz = dev_read_u32_default(bus, "spi-max-frequency",
|
||||
STM32_QSPI_DEFAULT_SCK_FREQ);
|
||||
/* clear flags */
|
||||
writel(STM32_QSPI_FCR_CTCF | STM32_QSPI_FCR_CTEF, &priv->regs->fcr);
|
||||
|
||||
plat->base = res_regs.start;
|
||||
plat->memory_map = res_mem.start;
|
||||
return ret;
|
||||
}
|
||||
|
||||
debug("%s: regs=<0x%x> mapped=<0x%x>, max-frequency=%d\n",
|
||||
__func__,
|
||||
plat->base,
|
||||
plat->memory_map,
|
||||
plat->max_hz
|
||||
);
|
||||
static void _stm32_qspi_read_fifo(u8 *val, void __iomem *addr)
|
||||
{
|
||||
*val = readb(addr);
|
||||
}
|
||||
|
||||
static void _stm32_qspi_write_fifo(u8 *val, void __iomem *addr)
|
||||
{
|
||||
writeb(*val, addr);
|
||||
}
|
||||
|
||||
static int _stm32_qspi_poll(struct stm32_qspi_priv *priv,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
void (*fifo)(u8 *val, void __iomem *addr);
|
||||
u32 len = op->data.nbytes, sr;
|
||||
u8 *buf;
|
||||
int ret;
|
||||
|
||||
if (op->data.dir == SPI_MEM_DATA_IN) {
|
||||
fifo = _stm32_qspi_read_fifo;
|
||||
buf = op->data.buf.in;
|
||||
|
||||
} else {
|
||||
fifo = _stm32_qspi_write_fifo;
|
||||
buf = (u8 *)op->data.buf.out;
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
ret = readl_poll_timeout(&priv->regs->sr, sr,
|
||||
sr & STM32_QSPI_SR_FTF,
|
||||
STM32_QSPI_FIFO_TIMEOUT_US);
|
||||
if (ret) {
|
||||
pr_err("fifo timeout (len:%d stat:%#x)\n", len, sr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
fifo(buf++, &priv->regs->dr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_qspi_mm(struct stm32_qspi_priv *priv,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
memcpy_fromio(op->data.buf.in, priv->mm_base + op->addr.val,
|
||||
op->data.nbytes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _stm32_qspi_tx(struct stm32_qspi_priv *priv,
|
||||
const struct spi_mem_op *op,
|
||||
u8 mode)
|
||||
{
|
||||
if (!op->data.nbytes)
|
||||
return 0;
|
||||
|
||||
if (mode == STM32_QSPI_CCR_MEM_MAP)
|
||||
return stm32_qspi_mm(priv, op);
|
||||
|
||||
return _stm32_qspi_poll(priv, op);
|
||||
}
|
||||
|
||||
static int _stm32_qspi_get_mode(u8 buswidth)
|
||||
{
|
||||
if (buswidth == 4)
|
||||
return 3;
|
||||
|
||||
return buswidth;
|
||||
}
|
||||
|
||||
static int stm32_qspi_exec_op(struct spi_slave *slave,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct stm32_qspi_priv *priv = dev_get_priv(slave->dev->parent);
|
||||
u32 cr, ccr, addr_max;
|
||||
u8 mode = STM32_QSPI_CCR_IND_WRITE;
|
||||
int timeout, ret;
|
||||
|
||||
debug("%s: cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n",
|
||||
__func__, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
|
||||
op->dummy.buswidth, op->data.buswidth,
|
||||
op->addr.val, op->data.nbytes);
|
||||
|
||||
ret = _stm32_qspi_wait_for_not_busy(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
addr_max = op->addr.val + op->data.nbytes + 1;
|
||||
|
||||
if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes) {
|
||||
if (addr_max < priv->mm_size && op->addr.buswidth)
|
||||
mode = STM32_QSPI_CCR_MEM_MAP;
|
||||
else
|
||||
mode = STM32_QSPI_CCR_IND_READ;
|
||||
}
|
||||
|
||||
if (op->data.nbytes)
|
||||
writel(op->data.nbytes - 1, &priv->regs->dlr);
|
||||
|
||||
ccr = (mode << STM32_QSPI_CCR_FMODE_SHIFT);
|
||||
ccr |= op->cmd.opcode;
|
||||
ccr |= (_stm32_qspi_get_mode(op->cmd.buswidth)
|
||||
<< STM32_QSPI_CCR_IMODE_SHIFT);
|
||||
|
||||
if (op->addr.nbytes) {
|
||||
ccr |= ((op->addr.nbytes - 1) << STM32_QSPI_CCR_ADSIZE_SHIFT);
|
||||
ccr |= (_stm32_qspi_get_mode(op->addr.buswidth)
|
||||
<< STM32_QSPI_CCR_ADMODE_SHIFT);
|
||||
}
|
||||
|
||||
if (op->dummy.buswidth && op->dummy.nbytes)
|
||||
ccr |= (op->dummy.nbytes * 8 / op->dummy.buswidth
|
||||
<< STM32_QSPI_CCR_DCYC_SHIFT);
|
||||
|
||||
if (op->data.nbytes)
|
||||
ccr |= (_stm32_qspi_get_mode(op->data.buswidth)
|
||||
<< STM32_QSPI_CCR_DMODE_SHIFT);
|
||||
|
||||
writel(ccr, &priv->regs->ccr);
|
||||
|
||||
if (op->addr.nbytes && mode != STM32_QSPI_CCR_MEM_MAP)
|
||||
writel(op->addr.val, &priv->regs->ar);
|
||||
|
||||
ret = _stm32_qspi_tx(priv, op, mode);
|
||||
/*
|
||||
* Abort in:
|
||||
* -error case
|
||||
* -read memory map: prefetching must be stopped if we read the last
|
||||
* byte of device (device size - fifo size). like device size is not
|
||||
* knows, the prefetching is always stop.
|
||||
*/
|
||||
if (ret || mode == STM32_QSPI_CCR_MEM_MAP)
|
||||
goto abort;
|
||||
|
||||
/* Wait end of tx in indirect mode */
|
||||
ret = _stm32_qspi_wait_cmd(priv, op);
|
||||
if (ret)
|
||||
goto abort;
|
||||
|
||||
return 0;
|
||||
|
||||
abort:
|
||||
setbits_le32(&priv->regs->cr, STM32_QSPI_CR_ABORT);
|
||||
|
||||
/* Wait clear of abort bit by hw */
|
||||
timeout = readl_poll_timeout(&priv->regs->cr, cr,
|
||||
!(cr & STM32_QSPI_CR_ABORT),
|
||||
STM32_ABT_TIMEOUT_US);
|
||||
|
||||
writel(STM32_QSPI_FCR_CTCF, &priv->regs->fcr);
|
||||
|
||||
if (ret || timeout)
|
||||
pr_err("%s ret:%d abort timeout:%d\n", __func__, ret, timeout);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stm32_qspi_probe(struct udevice *bus)
|
||||
{
|
||||
struct stm32_qspi_platdata *plat = dev_get_platdata(bus);
|
||||
struct stm32_qspi_priv *priv = dev_get_priv(bus);
|
||||
struct dm_spi_bus *dm_spi_bus;
|
||||
struct resource res;
|
||||
struct clk clk;
|
||||
struct reset_ctl reset_ctl;
|
||||
int ret;
|
||||
|
||||
dm_spi_bus = bus->uclass_priv;
|
||||
ret = dev_read_resource_byname(bus, "qspi", &res);
|
||||
if (ret) {
|
||||
dev_err(bus, "can't get regs base addresses(ret = %d)!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dm_spi_bus->max_hz = plat->max_hz;
|
||||
priv->regs = (struct stm32_qspi_regs *)res.start;
|
||||
|
||||
priv->regs = (struct stm32_qspi_regs *)(uintptr_t)plat->base;
|
||||
ret = dev_read_resource_byname(bus, "qspi_mm", &res);
|
||||
if (ret) {
|
||||
dev_err(bus, "can't get mmap base address(ret = %d)!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->max_hz = plat->max_hz;
|
||||
priv->mm_base = (void __iomem *)res.start;
|
||||
|
||||
priv->mm_size = resource_size(&res);
|
||||
if (priv->mm_size > STM32_QSPI_MAX_MMAP_SZ)
|
||||
return -EINVAL;
|
||||
|
||||
debug("%s: regs=<0x%p> mapped=<0x%p> mapped_size=<0x%lx>\n",
|
||||
__func__, priv->regs, priv->mm_base, priv->mm_size);
|
||||
|
||||
ret = clk_get_by_index(bus, 0, &clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_enable(&clk);
|
||||
|
||||
if (ret) {
|
||||
dev_err(bus, "failed to enable clock\n");
|
||||
return ret;
|
||||
|
@ -499,78 +380,68 @@ static int stm32_qspi_probe(struct udevice *bus)
|
|||
reset_deassert(&reset_ctl);
|
||||
}
|
||||
|
||||
priv->cs_used = -1;
|
||||
|
||||
setbits_le32(&priv->regs->cr, STM32_QSPI_CR_SSHIFT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Set dcr fsize to max address */
|
||||
setbits_le32(&priv->regs->dcr,
|
||||
STM32_QSPI_DCR_FSIZE_MASK << STM32_QSPI_DCR_FSIZE_SHIFT);
|
||||
|
||||
static int stm32_qspi_remove(struct udevice *bus)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_qspi_claim_bus(struct udevice *dev)
|
||||
{
|
||||
struct stm32_qspi_priv *priv;
|
||||
struct udevice *bus;
|
||||
struct spi_flash *flash;
|
||||
struct dm_spi_slave_platdata *slave_plat;
|
||||
struct stm32_qspi_priv *priv = dev_get_priv(dev->parent);
|
||||
struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
|
||||
|
||||
bus = dev->parent;
|
||||
priv = dev_get_priv(bus);
|
||||
flash = dev_get_uclass_priv(dev);
|
||||
slave_plat = dev_get_parent_platdata(dev);
|
||||
|
||||
if (slave_plat->cs >= STM32_MAX_NORCHIP)
|
||||
if (slave_plat->cs >= STM32_QSPI_MAX_CHIP)
|
||||
return -ENODEV;
|
||||
|
||||
_stm32_qspi_set_cs(priv, slave_plat->cs);
|
||||
if (priv->cs_used != slave_plat->cs) {
|
||||
struct stm32_qspi_flash *flash = &priv->flash[slave_plat->cs];
|
||||
|
||||
_stm32_qspi_set_flash_size(priv, flash->size);
|
||||
priv->cs_used = slave_plat->cs;
|
||||
|
||||
_stm32_qspi_enable(priv);
|
||||
if (flash->initialized) {
|
||||
/* Set the configuration: speed + cs */
|
||||
writel(flash->cr, &priv->regs->cr);
|
||||
writel(flash->dcr, &priv->regs->dcr);
|
||||
} else {
|
||||
/* Set chip select */
|
||||
clrsetbits_le32(&priv->regs->cr, STM32_QSPI_CR_FSEL,
|
||||
priv->cs_used ? STM32_QSPI_CR_FSEL : 0);
|
||||
|
||||
/* Save the configuration: speed + cs */
|
||||
flash->cr = readl(&priv->regs->cr);
|
||||
flash->dcr = readl(&priv->regs->dcr);
|
||||
|
||||
flash->initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
setbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_qspi_release_bus(struct udevice *dev)
|
||||
{
|
||||
struct stm32_qspi_priv *priv;
|
||||
struct udevice *bus;
|
||||
struct stm32_qspi_priv *priv = dev_get_priv(dev->parent);
|
||||
|
||||
bus = dev->parent;
|
||||
priv = dev_get_priv(bus);
|
||||
|
||||
_stm32_qspi_disable(priv);
|
||||
clrbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_qspi_xfer(struct udevice *dev, unsigned int bitlen,
|
||||
const void *dout, void *din, unsigned long flags)
|
||||
{
|
||||
struct stm32_qspi_priv *priv;
|
||||
struct udevice *bus;
|
||||
struct spi_flash *flash;
|
||||
|
||||
bus = dev->parent;
|
||||
priv = dev_get_priv(bus);
|
||||
flash = dev_get_uclass_priv(dev);
|
||||
|
||||
return _stm32_qspi_xfer(priv, flash, bitlen, (const u8 *)dout,
|
||||
(u8 *)din, flags);
|
||||
}
|
||||
|
||||
static int stm32_qspi_set_speed(struct udevice *bus, uint speed)
|
||||
{
|
||||
struct stm32_qspi_platdata *plat = bus->platdata;
|
||||
struct stm32_qspi_priv *priv = dev_get_priv(bus);
|
||||
u32 qspi_clk = priv->clock_rate;
|
||||
u32 prescaler = 255;
|
||||
u32 csht;
|
||||
|
||||
if (speed > plat->max_hz)
|
||||
speed = plat->max_hz;
|
||||
int ret;
|
||||
|
||||
if (speed > 0) {
|
||||
prescaler = DIV_ROUND_UP(qspi_clk, speed) - 1;
|
||||
|
@ -583,7 +454,9 @@ static int stm32_qspi_set_speed(struct udevice *bus, uint speed)
|
|||
csht = DIV_ROUND_UP((5 * qspi_clk) / (prescaler + 1), 100000000);
|
||||
csht = (csht - 1) & STM32_QSPI_DCR_CSHT_MASK;
|
||||
|
||||
_stm32_qspi_wait_for_not_busy(priv);
|
||||
ret = _stm32_qspi_wait_for_not_busy(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clrsetbits_le32(&priv->regs->cr,
|
||||
STM32_QSPI_CR_PRESCALER_MASK <<
|
||||
|
@ -603,8 +476,11 @@ static int stm32_qspi_set_speed(struct udevice *bus, uint speed)
|
|||
static int stm32_qspi_set_mode(struct udevice *bus, uint mode)
|
||||
{
|
||||
struct stm32_qspi_priv *priv = dev_get_priv(bus);
|
||||
int ret;
|
||||
|
||||
_stm32_qspi_wait_for_not_busy(priv);
|
||||
ret = _stm32_qspi_wait_for_not_busy(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((mode & SPI_CPHA) && (mode & SPI_CPOL))
|
||||
setbits_le32(&priv->regs->dcr, STM32_QSPI_DCR_CKMODE);
|
||||
|
@ -616,20 +492,6 @@ static int stm32_qspi_set_mode(struct udevice *bus, uint mode)
|
|||
if (mode & SPI_CS_HIGH)
|
||||
return -ENODEV;
|
||||
|
||||
if (mode & SPI_RX_QUAD)
|
||||
priv->mode |= SPI_RX_QUAD;
|
||||
else if (mode & SPI_RX_DUAL)
|
||||
priv->mode |= SPI_RX_DUAL;
|
||||
else
|
||||
priv->mode &= ~(SPI_RX_QUAD | SPI_RX_DUAL);
|
||||
|
||||
if (mode & SPI_TX_QUAD)
|
||||
priv->mode |= SPI_TX_QUAD;
|
||||
else if (mode & SPI_TX_DUAL)
|
||||
priv->mode |= SPI_TX_DUAL;
|
||||
else
|
||||
priv->mode &= ~(SPI_TX_QUAD | SPI_TX_DUAL);
|
||||
|
||||
debug("%s: regs=%p, mode=%d rx: ", __func__, priv->regs, mode);
|
||||
|
||||
if (mode & SPI_RX_QUAD)
|
||||
|
@ -649,12 +511,16 @@ static int stm32_qspi_set_mode(struct udevice *bus, uint mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_controller_mem_ops stm32_qspi_mem_ops = {
|
||||
.exec_op = stm32_qspi_exec_op,
|
||||
};
|
||||
|
||||
static const struct dm_spi_ops stm32_qspi_ops = {
|
||||
.claim_bus = stm32_qspi_claim_bus,
|
||||
.release_bus = stm32_qspi_release_bus,
|
||||
.xfer = stm32_qspi_xfer,
|
||||
.set_speed = stm32_qspi_set_speed,
|
||||
.set_mode = stm32_qspi_set_mode,
|
||||
.mem_ops = &stm32_qspi_mem_ops,
|
||||
};
|
||||
|
||||
static const struct udevice_id stm32_qspi_ids[] = {
|
||||
|
@ -664,13 +530,10 @@ static const struct udevice_id stm32_qspi_ids[] = {
|
|||
};
|
||||
|
||||
U_BOOT_DRIVER(stm32_qspi) = {
|
||||
.name = "stm32_qspi",
|
||||
.id = UCLASS_SPI,
|
||||
.name = "stm32_qspi",
|
||||
.id = UCLASS_SPI,
|
||||
.of_match = stm32_qspi_ids,
|
||||
.ops = &stm32_qspi_ops,
|
||||
.ofdata_to_platdata = stm32_qspi_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct stm32_qspi_platdata),
|
||||
.ops = &stm32_qspi_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct stm32_qspi_priv),
|
||||
.probe = stm32_qspi_probe,
|
||||
.remove = stm32_qspi_remove,
|
||||
.probe = stm32_qspi_probe,
|
||||
};
|
||||
|
|
|
@ -10,17 +10,17 @@
|
|||
#include <linux/sizes.h>
|
||||
#include <asm/arch/stm32.h>
|
||||
|
||||
#define CONFIG_PREBOOT
|
||||
|
||||
/*
|
||||
* Number of clock ticks in 1 sec
|
||||
*/
|
||||
#define CONFIG_SYS_HZ 1000
|
||||
|
||||
#ifndef CONFIG_STM32MP1_TRUSTED
|
||||
/* PSCI support */
|
||||
#define CONFIG_ARMV7_PSCI_1_0
|
||||
#define CONFIG_ARMV7_SECURE_BASE STM32_SYSRAM_BASE
|
||||
#define CONFIG_ARMV7_SECURE_MAX_SIZE STM32_SYSRAM_SIZE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* malloc() pool size
|
||||
|
@ -53,6 +53,9 @@
|
|||
#define CONFIG_SETUP_MEMORY_TAGS
|
||||
#define CONFIG_INITRD_TAG
|
||||
|
||||
/* Extend size of kernel image for uncompression */
|
||||
#define CONFIG_SYS_BOOTM_LEN SZ_32M
|
||||
|
||||
/* SPL support */
|
||||
#ifdef CONFIG_SPL
|
||||
/* BOOTROM load address */
|
||||
|
@ -69,36 +72,65 @@
|
|||
STM32_SYSRAM_SIZE)
|
||||
#endif /* #ifdef CONFIG_SPL */
|
||||
|
||||
#define CONFIG_SYS_MEMTEST_START STM32_DDR_BASE
|
||||
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + SZ_64M)
|
||||
#define CONFIG_SYS_MEMTEST_SCRATCH (CONFIG_SYS_MEMTEST_END + 4)
|
||||
|
||||
/*MMC SD*/
|
||||
#define CONFIG_SYS_MMC_MAX_DEVICE 3
|
||||
#define CONFIG_SUPPORT_EMMC_BOOT
|
||||
|
||||
#if !defined(CONFIG_SPL) || !defined(CONFIG_SPL_BUILD)
|
||||
/*****************************************************************************/
|
||||
#ifdef CONFIG_DISTRO_DEFAULTS
|
||||
/*****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_SPL_BUILD)
|
||||
|
||||
#define BOOT_TARGET_DEVICES(func) \
|
||||
func(MMC, mmc, 1) \
|
||||
func(MMC, mmc, 0) \
|
||||
func(MMC, mmc, 2)
|
||||
/*
|
||||
* bootcmd for stm32mp1:
|
||||
* for serial/usb: execute the stm32prog command
|
||||
* for mmc boot (eMMC, SD card), boot only on the same device
|
||||
* for nand boot, boot with on ubifs partition on nand
|
||||
* for nor boot, use the default order
|
||||
*/
|
||||
#define CONFIG_PREBOOT
|
||||
|
||||
#define STM32MP_BOOTCMD "bootcmd_stm32mp=" \
|
||||
"echo \"Boot over ${boot_device}${boot_instance}!\";" \
|
||||
"if test ${boot_device} = serial || test ${boot_device} = usb;" \
|
||||
"then stm32prog ${boot_device} ${boot_instance}; " \
|
||||
"else " \
|
||||
"if test ${boot_device} = mmc;" \
|
||||
"then env set boot_targets \"mmc${boot_instance}\"; fi;" \
|
||||
"if test ${boot_device} = nand;" \
|
||||
"then env set boot_targets ubifs0; fi;" \
|
||||
"run distro_bootcmd;" \
|
||||
"fi;\0"
|
||||
|
||||
#include <config_distro_bootcmd.h>
|
||||
|
||||
#define STM32MP_PREBOOT \
|
||||
"echo \"Boot over ${boot_device}${boot_instance}!\"; " \
|
||||
"if test \"${boot_device}\" = \"mmc\"; then " \
|
||||
"env set boot_targets \"mmc${boot_instance}\"; "\
|
||||
"fi;"
|
||||
|
||||
/*
|
||||
* memory layout for 32M uncompressed/compressed kernel,
|
||||
* 1M fdt, 1M script, 1M pxe and 1M for splashimage
|
||||
* and the ramdisk at the end.
|
||||
*/
|
||||
#define CONFIG_EXTRA_ENV_SETTINGS \
|
||||
"scriptaddr=0xC0000000\0" \
|
||||
"pxefile_addr_r=0xC0000000\0" \
|
||||
"kernel_addr_r=0xC1000000\0" \
|
||||
"fdt_addr_r=0xC4000000\0" \
|
||||
"ramdisk_addr_r=0xC4100000\0" \
|
||||
"kernel_addr_r=0xc2000000\0" \
|
||||
"fdt_addr_r=0xc4000000\0" \
|
||||
"scriptaddr=0xc4100000\0" \
|
||||
"pxefile_addr_r=0xc4200000\0" \
|
||||
"splashimage=0xc4300000\0" \
|
||||
"ramdisk_addr_r=0xc4400000\0" \
|
||||
"fdt_high=0xffffffff\0" \
|
||||
"initrd_high=0xffffffff\0" \
|
||||
"preboot=" STM32MP_PREBOOT "\0" \
|
||||
STM32MP_BOOTCMD \
|
||||
BOOTENV
|
||||
|
||||
#endif /* ifndef CONFIG_SPL_BUILD */
|
||||
#endif /* ifdef CONFIG_DISTRO_DEFAULTS*/
|
||||
|
||||
#endif /* __CONFIG_H */
|
||||
|
|
46
include/dt-bindings/mfd/st,stpmic1.h
Normal file
46
include/dt-bindings/mfd/st,stpmic1.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
||||
* Author: Philippe Peurichard <philippe.peurichard@st.com>,
|
||||
* Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_STPMIC1_H__
|
||||
#define __DT_BINDINGS_STPMIC1_H__
|
||||
|
||||
/* IRQ definitions */
|
||||
#define IT_PONKEY_F 0
|
||||
#define IT_PONKEY_R 1
|
||||
#define IT_WAKEUP_F 2
|
||||
#define IT_WAKEUP_R 3
|
||||
#define IT_VBUS_OTG_F 4
|
||||
#define IT_VBUS_OTG_R 5
|
||||
#define IT_SWOUT_F 6
|
||||
#define IT_SWOUT_R 7
|
||||
|
||||
#define IT_CURLIM_BUCK1 8
|
||||
#define IT_CURLIM_BUCK2 9
|
||||
#define IT_CURLIM_BUCK3 10
|
||||
#define IT_CURLIM_BUCK4 11
|
||||
#define IT_OCP_OTG 12
|
||||
#define IT_OCP_SWOUT 13
|
||||
#define IT_OCP_BOOST 14
|
||||
#define IT_OVP_BOOST 15
|
||||
|
||||
#define IT_CURLIM_LDO1 16
|
||||
#define IT_CURLIM_LDO2 17
|
||||
#define IT_CURLIM_LDO3 18
|
||||
#define IT_CURLIM_LDO4 19
|
||||
#define IT_CURLIM_LDO5 20
|
||||
#define IT_CURLIM_LDO6 21
|
||||
#define IT_SHORT_SWOTG 22
|
||||
#define IT_SHORT_SWOUT 23
|
||||
|
||||
#define IT_TWARN_F 24
|
||||
#define IT_TWARN_R 25
|
||||
#define IT_VINLOW_F 26
|
||||
#define IT_VINLOW_R 27
|
||||
#define IT_SWIN_F 30
|
||||
#define IT_SWIN_R 31
|
||||
|
||||
#endif /* __DT_BINDINGS_STPMIC1_H__ */
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* This file is part of stpmu1 pmic driver
|
||||
*
|
||||
* Copyright (C) 2017, STMicroelectronics - All Rights Reserved
|
||||
* Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
|
||||
*
|
||||
* License type: GPLv2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_STPMU1_H__
|
||||
#define __DT_BINDINGS_STPMU1_H__
|
||||
|
||||
/* IRQ definitions */
|
||||
#define IT_PONKEY_F 0
|
||||
#define IT_PONKEY_R 1
|
||||
#define IT_WAKEUP_F 2
|
||||
#define IT_WAKEUP_R 3
|
||||
#define IT_VBUS_OTG_F 4
|
||||
#define IT_VBUS_OTG_R 5
|
||||
#define IT_SWOUT_F 6
|
||||
#define IT_SWOUT_R 7
|
||||
|
||||
#define IT_CURLIM_BUCK1 8
|
||||
#define IT_CURLIM_BUCK2 9
|
||||
#define IT_CURLIM_BUCK3 10
|
||||
#define IT_CURLIM_BUCK4 11
|
||||
#define IT_OCP_OTG 12
|
||||
#define IT_OCP_SWOUT 13
|
||||
#define IT_OCP_BOOST 14
|
||||
#define IT_OVP_BOOST 15
|
||||
|
||||
#define IT_CURLIM_LDO1 16
|
||||
#define IT_CURLIM_LDO2 17
|
||||
#define IT_CURLIM_LDO3 18
|
||||
#define IT_CURLIM_LDO4 19
|
||||
#define IT_CURLIM_LDO5 20
|
||||
#define IT_CURLIM_LDO6 21
|
||||
#define IT_SHORT_SWOTG 22
|
||||
#define IT_SHORT_SWOUT 23
|
||||
|
||||
#define IT_TWARN_F 24
|
||||
#define IT_TWARN_R 25
|
||||
#define IT_VINLOW_F 26
|
||||
#define IT_VINLOW_R 27
|
||||
#define IT_SWIN_F 30
|
||||
#define IT_SWIN_R 31
|
||||
|
||||
#endif /* __DT_BINDINGS_STPMU1_H__ */
|
117
include/power/stpmic1.h
Normal file
117
include/power/stpmic1.h
Normal file
|
@ -0,0 +1,117 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
#ifndef __PMIC_STPMIC1_H_
|
||||
#define __PMIC_STPMIC1_H_
|
||||
|
||||
#define STPMIC1_MAIN_CR 0x10
|
||||
#define STPMIC1_BUCKS_MRST_CR 0x18
|
||||
#define STPMIC1_LDOS_MRST_CR 0x1a
|
||||
#define STPMIC1_BUCKX_MAIN_CR(buck) (0x20 + (buck))
|
||||
#define STPMIC1_REFDDR_MAIN_CR 0x24
|
||||
#define STPMIC1_LDOX_MAIN_CR(ldo) (0x25 + (ldo))
|
||||
#define STPMIC1_BST_SW_CR 0x40
|
||||
#define STPMIC1_NVM_SR 0xb8
|
||||
#define STPMIC1_NVM_CR 0xb9
|
||||
|
||||
/* Main PMIC Control Register (MAIN_CR) */
|
||||
#define STPMIC1_SWOFF BIT(0)
|
||||
#define STPMIC1_RREQ_EN BIT(1)
|
||||
|
||||
/* BUCKS_MRST_CR */
|
||||
#define STPMIC1_MRST_BUCK(buck) BIT(buck)
|
||||
#define STPMIC1_MRST_BUCK_ALL GENMASK(3, 0)
|
||||
|
||||
/* LDOS_MRST_CR */
|
||||
#define STPMIC1_MRST_LDO(ldo) BIT(ldo)
|
||||
#define STPMIC1_MRST_LDO_ALL GENMASK(6, 0)
|
||||
|
||||
/* BUCKx_MAIN_CR (x=1...4) */
|
||||
#define STPMIC1_BUCK_ENA BIT(0)
|
||||
#define STPMIC1_BUCK_PREG_MODE BIT(1)
|
||||
#define STPMIC1_BUCK_VOUT_MASK GENMASK(7, 2)
|
||||
#define STPMIC1_BUCK_VOUT_SHIFT 2
|
||||
#define STPMIC1_BUCK_VOUT(sel) (sel << STPMIC1_BUCK_VOUT_SHIFT)
|
||||
|
||||
#define STPMIC1_BUCK2_1200000V STPMIC1_BUCK_VOUT(24)
|
||||
#define STPMIC1_BUCK2_1350000V STPMIC1_BUCK_VOUT(30)
|
||||
|
||||
#define STPMIC1_BUCK3_1800000V STPMIC1_BUCK_VOUT(39)
|
||||
|
||||
/* REFDDR_MAIN_CR */
|
||||
#define STPMIC1_VREF_ENA BIT(0)
|
||||
|
||||
/* LDOX_MAIN_CR */
|
||||
#define STPMIC1_LDO_ENA BIT(0)
|
||||
#define STPMIC1_LDO12356_VOUT_MASK GENMASK(6, 2)
|
||||
#define STPMIC1_LDO12356_VOUT_SHIFT 2
|
||||
#define STPMIC1_LDO_VOUT(sel) (sel << STPMIC1_LDO12356_VOUT_SHIFT)
|
||||
|
||||
#define STPMIC1_LDO3_MODE BIT(7)
|
||||
#define STPMIC1_LDO3_DDR_SEL 31
|
||||
#define STPMIC1_LDO3_1800000 STPMIC1_LDO_VOUT(9)
|
||||
|
||||
#define STPMIC1_LDO4_UV 3300000
|
||||
|
||||
/* BST_SW_CR */
|
||||
#define STPMIC1_BST_ON BIT(0)
|
||||
#define STPMIC1_VBUSOTG_ON BIT(1)
|
||||
#define STPMIC1_SWOUT_ON BIT(2)
|
||||
#define STPMIC1_PWR_SW_ON (STPMIC1_VBUSOTG_ON | STPMIC1_SWOUT_ON)
|
||||
|
||||
/* NVM_SR */
|
||||
#define STPMIC1_NVM_BUSY BIT(0)
|
||||
|
||||
/* NVM_CR */
|
||||
#define STPMIC1_NVM_CMD_PROGRAM 1
|
||||
#define STPMIC1_NVM_CMD_READ 2
|
||||
|
||||
/* Timeout */
|
||||
#define STPMIC1_DEFAULT_START_UP_DELAY_MS 1
|
||||
#define STPMIC1_DEFAULT_STOP_DELAY_MS 5
|
||||
#define STPMIC1_USB_BOOST_START_UP_DELAY_MS 10
|
||||
|
||||
enum {
|
||||
STPMIC1_BUCK1,
|
||||
STPMIC1_BUCK2,
|
||||
STPMIC1_BUCK3,
|
||||
STPMIC1_BUCK4,
|
||||
STPMIC1_MAX_BUCK,
|
||||
};
|
||||
|
||||
enum {
|
||||
STPMIC1_PREG_MODE_HP,
|
||||
STPMIC1_PREG_MODE_LP,
|
||||
};
|
||||
|
||||
enum {
|
||||
STPMIC1_LDO1,
|
||||
STPMIC1_LDO2,
|
||||
STPMIC1_LDO3,
|
||||
STPMIC1_LDO4,
|
||||
STPMIC1_LDO5,
|
||||
STPMIC1_LDO6,
|
||||
STPMIC1_MAX_LDO,
|
||||
};
|
||||
|
||||
enum {
|
||||
STPMIC1_LDO_MODE_NORMAL,
|
||||
STPMIC1_LDO_MODE_BYPASS,
|
||||
STPMIC1_LDO_MODE_SINK_SOURCE,
|
||||
};
|
||||
|
||||
enum {
|
||||
STPMIC1_PWR_SW1,
|
||||
STPMIC1_PWR_SW2,
|
||||
STPMIC1_MAX_PWR_SW,
|
||||
};
|
||||
|
||||
int stpmic1_shadow_read_byte(u8 addr, u8 *buf);
|
||||
int stpmic1_shadow_write_byte(u8 addr, u8 *buf);
|
||||
int stpmic1_nvm_read_byte(u8 addr, u8 *buf);
|
||||
int stpmic1_nvm_write_byte(u8 addr, u8 *buf);
|
||||
int stpmic1_nvm_read_all(u8 *buf, int buf_len);
|
||||
int stpmic1_nvm_write_all(u8 *buf, int buf_len);
|
||||
#endif
|
|
@ -1,85 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
#ifndef __PMIC_STPMU1_H_
|
||||
#define __PMIC_STPMU1_H_
|
||||
|
||||
#define STPMU1_MASK_RESET_BUCK 0x18
|
||||
#define STPMU1_BUCKX_CTRL_REG(buck) (0x20 + (buck))
|
||||
#define STPMU1_VREF_CTRL_REG 0x24
|
||||
#define STPMU1_LDOX_CTRL_REG(ldo) (0x25 + (ldo))
|
||||
#define STPMU1_USB_CTRL_REG 0x40
|
||||
#define STPMU1_NVM_USER_STATUS_REG 0xb8
|
||||
#define STPMU1_NVM_USER_CONTROL_REG 0xb9
|
||||
|
||||
#define STPMU1_MASK_RESET_BUCK3 BIT(2)
|
||||
|
||||
#define STPMU1_BUCK_EN BIT(0)
|
||||
#define STPMU1_BUCK_MODE BIT(1)
|
||||
#define STPMU1_BUCK_OUTPUT_MASK GENMASK(7, 2)
|
||||
#define STPMU1_BUCK_OUTPUT_SHIFT 2
|
||||
#define STPMU1_BUCK2_1200000V (24 << STPMU1_BUCK_OUTPUT_SHIFT)
|
||||
#define STPMU1_BUCK2_1350000V (30 << STPMU1_BUCK_OUTPUT_SHIFT)
|
||||
#define STPMU1_BUCK3_1800000V (39 << STPMU1_BUCK_OUTPUT_SHIFT)
|
||||
|
||||
#define STPMU1_VREF_EN BIT(0)
|
||||
|
||||
#define STPMU1_LDO_EN BIT(0)
|
||||
#define STPMU1_LDO12356_OUTPUT_MASK GENMASK(6, 2)
|
||||
#define STPMU1_LDO12356_OUTPUT_SHIFT 2
|
||||
#define STPMU1_LDO3_MODE BIT(7)
|
||||
#define STPMU1_LDO3_DDR_SEL 31
|
||||
#define STPMU1_LDO3_1800000 (9 << STPMU1_LDO12356_OUTPUT_SHIFT)
|
||||
#define STPMU1_LDO4_UV 3300000
|
||||
|
||||
#define STPMU1_USB_BOOST_EN BIT(0)
|
||||
#define STPMU1_USB_PWR_SW_EN GENMASK(2, 1)
|
||||
|
||||
#define STPMU1_NVM_USER_CONTROL_PROGRAM BIT(0)
|
||||
#define STPMU1_NVM_USER_CONTROL_READ BIT(1)
|
||||
|
||||
#define STPMU1_NVM_USER_STATUS_BUSY BIT(0)
|
||||
#define STPMU1_NVM_USER_STATUS_ERROR BIT(1)
|
||||
|
||||
#define STPMU1_DEFAULT_START_UP_DELAY_MS 1
|
||||
#define STPMU1_DEFAULT_STOP_DELAY_MS 5
|
||||
#define STPMU1_USB_BOOST_START_UP_DELAY_MS 10
|
||||
|
||||
enum {
|
||||
STPMU1_BUCK1,
|
||||
STPMU1_BUCK2,
|
||||
STPMU1_BUCK3,
|
||||
STPMU1_BUCK4,
|
||||
STPMU1_MAX_BUCK,
|
||||
};
|
||||
|
||||
enum {
|
||||
STPMU1_BUCK_MODE_HP,
|
||||
STPMU1_BUCK_MODE_LP,
|
||||
};
|
||||
|
||||
enum {
|
||||
STPMU1_LDO1,
|
||||
STPMU1_LDO2,
|
||||
STPMU1_LDO3,
|
||||
STPMU1_LDO4,
|
||||
STPMU1_LDO5,
|
||||
STPMU1_LDO6,
|
||||
STPMU1_MAX_LDO,
|
||||
};
|
||||
|
||||
enum {
|
||||
STPMU1_LDO_MODE_NORMAL,
|
||||
STPMU1_LDO_MODE_BYPASS,
|
||||
STPMU1_LDO_MODE_SINK_SOURCE,
|
||||
};
|
||||
|
||||
enum {
|
||||
STPMU1_PWR_SW1,
|
||||
STPMU1_PWR_SW2,
|
||||
STPMU1_MAX_PWR_SW,
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue