mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
- arch and board update for stm32mp15:
- use OPP information in device tree for 800MHz/650MHz support - ram: inprovments of test command - solve boot on closed chip when access to DBGMCU_IDC is protected - stm32prog command: Add "device anme" during USB enumeration - update configs: activate WATCHDOG and 'env erase' command, increase teed partition, support SD card after NOR boot by default and use env info in env_check - some sboard cleanups: gpio hog in dh board, specific driver for type-c stusb1600 controller code in a driver move part of code in spl.c and in common directory - fix STM32 compatible for dwc_eth_qos driver - support of new pinctrl ops get_dir_flags/set_dir_flags in stm32 and stmfx drivers - vrefbuf: fix a possible overshoot when re-enabling -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEE56Yx6b9SnloYCWtD4rK92eCqk3UFAl8EgGEACgkQ4rK92eCq k3V7mwf+N5Iq6CbUPP11mFiNgAFZ5+hcn6gBTWvbjnd+oaIp15hiQrUNusGNFxXe oyM4fvm12tjuWFlA0U6VtiLhuVQB1Yte048oX+edDCCLGwxkp6cKBHtCaGT14XvY ow60XInv/dlrINumf8isy+5QlLgT1Cb7aGZN1qRHsUtnHB/IC836KO+hukGRUvk3 Lqz+FbHqitKnL+CIboC2+YzXqG6ZXdixFZVVPmTVd34C8hQOdkExJ//uR/lH/s6f vjaecs7HpIuKRpKpt5WcoLzTLd1hstqNNhmTbBHmVo+EqIjMkpISUwDpDJNU5pki BPbdG9VXqb46JLaTtPT+U4gX4yJ3Bw== =jQCC -----END PGP SIGNATURE----- Merge tag 'u-boot-stm32-20200707' of https://gitlab.denx.de/u-boot/custodians/u-boot-stm - arch and board update for stm32mp15: - use OPP information in device tree for 800MHz/650MHz support - ram: inprovments of test command - solve boot on closed chip when access to DBGMCU_IDC is protected - stm32prog command: Add "device anme" during USB enumeration - update configs: activate WATCHDOG and 'env erase' command, increase teed partition, support SD card after NOR boot by default and use env info in env_check - some sboard cleanups: gpio hog in dh board, specific driver for type-c stusb1600 controller code in a driver move part of code in spl.c and in common directory - fix STM32 compatible for dwc_eth_qos driver - support of new pinctrl ops get_dir_flags/set_dir_flags in stm32 and stmfx drivers - vrefbuf: fix a possible overshoot when re-enabling
This commit is contained in:
commit
1e88e78177
39 changed files with 1165 additions and 459 deletions
|
@ -65,7 +65,7 @@
|
|||
};
|
||||
|
||||
&bsec {
|
||||
u-boot,dm-pre-proper;
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
&clk_csi {
|
||||
|
@ -88,6 +88,16 @@
|
|||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
&cpu0_opp_table {
|
||||
u-boot,dm-spl;
|
||||
opp-650000000 {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
opp-800000000 {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
};
|
||||
|
||||
&gpioa {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
|
|
@ -20,6 +20,24 @@
|
|||
clock-frequency = <650000000>;
|
||||
device_type = "cpu";
|
||||
reg = <0>;
|
||||
operating-points-v2 = <&cpu0_opp_table>;
|
||||
nvmem-cells = <&part_number_otp>;
|
||||
nvmem-cell-names = "part_number";
|
||||
};
|
||||
};
|
||||
|
||||
cpu0_opp_table: cpu0-opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
opp-650000000 {
|
||||
opp-hz = /bits/ 64 <650000000>;
|
||||
opp-microvolt = <1200000>;
|
||||
opp-supported-hw = <0x1>;
|
||||
};
|
||||
opp-800000000 {
|
||||
opp-hz = /bits/ 64 <800000000>;
|
||||
opp-microvolt = <1350000>;
|
||||
opp-supported-hw = <0x2>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -1522,6 +1540,9 @@
|
|||
reg = <0x5c005000 0x400>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
part_number_otp: part_number_otp@4 {
|
||||
reg = <0x4 0x1>;
|
||||
};
|
||||
ts_cal1: calib@5c {
|
||||
reg = <0x5c 0x2>;
|
||||
};
|
||||
|
|
|
@ -133,15 +133,6 @@
|
|||
CLK_LPTIM45_LSE
|
||||
>;
|
||||
|
||||
/* VCO = 1300.0 MHz => P = 650 (CPU) */
|
||||
pll1: st,pll@0 {
|
||||
compatible = "st,stm32mp1-pll";
|
||||
reg = <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 {
|
||||
compatible = "st,stm32mp1-pll";
|
||||
|
|
|
@ -129,15 +129,6 @@
|
|||
CLK_LPTIM45_LSE
|
||||
>;
|
||||
|
||||
/* VCO = 1300.0 MHz => P = 650 (CPU) */
|
||||
pll1: st,pll@0 {
|
||||
compatible = "st,stm32mp1-pll";
|
||||
reg = <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 {
|
||||
compatible = "st,stm32mp1-pll";
|
||||
|
|
|
@ -107,6 +107,14 @@
|
|||
};
|
||||
};
|
||||
|
||||
&cpu0{
|
||||
cpu-supply = <&vddcore>;
|
||||
};
|
||||
|
||||
&cpu1{
|
||||
cpu-supply = <&vddcore>;
|
||||
};
|
||||
|
||||
&dac {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&dac_ch1_pins_a &dac_ch2_pins_a>;
|
||||
|
|
|
@ -235,15 +235,6 @@
|
|||
CLK_LPTIM45_LSE
|
||||
>;
|
||||
|
||||
/* VCO = 1300.0 MHz => P = 650 (CPU) */
|
||||
pll1: st,pll@0 {
|
||||
compatible = "st,stm32mp1-pll";
|
||||
reg = <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 {
|
||||
compatible = "st,stm32mp1-pll";
|
||||
|
|
|
@ -114,15 +114,6 @@
|
|||
CLK_LPTIM45_LSE
|
||||
>;
|
||||
|
||||
/* VCO = 1300.0 MHz => P = 650 (CPU) */
|
||||
pll1: st,pll@0 {
|
||||
compatible = "st,stm32mp1-pll";
|
||||
reg = <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 {
|
||||
compatible = "st,stm32mp1-pll";
|
||||
|
|
|
@ -116,6 +116,14 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
&cpu0{
|
||||
cpu-supply = <&vddcore>;
|
||||
};
|
||||
|
||||
&cpu1{
|
||||
cpu-supply = <&vddcore>;
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
status = "okay";
|
||||
pinctrl-0 = <ðernet0_rgmii_pins_a>;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
if ARCH_STM32MP
|
||||
|
||||
config SPL
|
||||
select SPL_BOARD_INIT
|
||||
select SPL_CLK
|
||||
select SPL_DM
|
||||
select SPL_DM_SEQ_ALIAS
|
||||
|
@ -46,6 +45,7 @@ config STM32MP15x
|
|||
select STM32_RESET
|
||||
select STM32_SERIAL
|
||||
select SYS_ARCH_TIMER
|
||||
imply CMD_NVEDIT_INFO
|
||||
imply SYSRESET_PSCI if TFABOOT
|
||||
imply SYSRESET_SYSCON if !TFABOOT
|
||||
help
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
obj-y += cpu.o
|
||||
obj-y += dram_init.o
|
||||
obj-y += syscon.o
|
||||
obj-y += bsec.o
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
obj-y += spl.o
|
||||
else
|
||||
obj-$(CONFIG_CMD_STM32PROG) += cmd_stm32prog/
|
||||
obj-y += bsec.o
|
||||
obj-$(CONFIG_CMD_STM32KEY) += cmd_stm32key.o
|
||||
obj-$(CONFIG_ARMV7_PSCI) += psci.o
|
||||
obj-$(CONFIG_TFABOOT) += boot_params.o
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <log.h>
|
||||
#include <misc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/bsec.h>
|
||||
#include <asm/arch/stm32mp1_smc.h>
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
@ -21,6 +22,7 @@
|
|||
#define BSEC_OTP_WRDATA_OFF 0x008
|
||||
#define BSEC_OTP_STATUS_OFF 0x00C
|
||||
#define BSEC_OTP_LOCK_OFF 0x010
|
||||
#define BSEC_DENABLE_OFF 0x014
|
||||
#define BSEC_DISTURBED_OFF 0x01C
|
||||
#define BSEC_ERROR_OFF 0x034
|
||||
#define BSEC_WRLOCK_OFF 0x04C /* OTP write permananet lock */
|
||||
|
@ -46,6 +48,9 @@
|
|||
#define BSEC_MODE_PROGFAIL_MASK 0x10
|
||||
#define BSEC_MODE_PWR_MASK 0x20
|
||||
|
||||
/* DENABLE Register */
|
||||
#define BSEC_DENABLE_DBGSWENABLE BIT(10)
|
||||
|
||||
/*
|
||||
* OTP Lock services definition
|
||||
* Value must corresponding to the bit number in the register
|
||||
|
@ -474,20 +479,23 @@ static int stm32mp_bsec_ofdata_to_platdata(struct udevice *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_TFABOOT
|
||||
static int stm32mp_bsec_probe(struct udevice *dev)
|
||||
{
|
||||
#if !defined(CONFIG_TFABOOT) && !defined(CONFIG_SPL_BUILD)
|
||||
int otp;
|
||||
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
|
||||
|
||||
/* update unlocked shadow for OTP cleared by the rom code */
|
||||
/*
|
||||
* update unlocked shadow for OTP cleared by the rom code
|
||||
* only executed in U-Boot proper when TF-A is not used
|
||||
*/
|
||||
for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++)
|
||||
if (!bsec_read_SR_lock(plat->base, otp))
|
||||
bsec_shadow_register(plat->base, otp);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct udevice_id stm32mp_bsec_ids[] = {
|
||||
{ .compatible = "st,stm32mp15-bsec" },
|
||||
|
@ -501,7 +509,25 @@ 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,
|
||||
#ifndef CONFIG_TFABOOT
|
||||
.probe = stm32mp_bsec_probe,
|
||||
#endif
|
||||
};
|
||||
|
||||
bool bsec_dbgswenable(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
struct stm32mp_bsec_platdata *plat;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_MISC,
|
||||
DM_GET_DRIVER(stm32mp_bsec), &dev);
|
||||
if (ret || !dev) {
|
||||
pr_debug("bsec driver not available\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
plat = dev_get_platdata(dev);
|
||||
if (readl(plat->base + BSEC_DENABLE_OFF) & BSEC_DENABLE_DBGSWENABLE)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -197,10 +197,12 @@ bool stm32prog_usb_loop(struct stm32prog_data *data, int dev)
|
|||
bool result;
|
||||
/* USB download gadget for STM32 Programmer */
|
||||
char product[128];
|
||||
char name[SOC_NAME_SIZE];
|
||||
|
||||
get_soc_name(name);
|
||||
snprintf(product, sizeof(product),
|
||||
"USB download gadget@Device ID /0x%03X, @Revision ID /0x%04X",
|
||||
get_cpu_dev(), get_cpu_rev());
|
||||
"USB download gadget@Device ID /0x%03X, @Revision ID /0x%04X, @Name /%s,",
|
||||
get_cpu_dev(), get_cpu_rev(), name);
|
||||
g_dnl_set_product(product);
|
||||
|
||||
if (stm32prog_data->phase == PHASE_FLASHLAYOUT) {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <misc.h>
|
||||
#include <net.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/bsec.h>
|
||||
#include <asm/arch/stm32.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <dm/device.h>
|
||||
|
@ -155,8 +156,13 @@ static void dbgmcu_init(void)
|
|||
{
|
||||
setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
|
||||
|
||||
/* Freeze IWDG2 if Cortex-A7 is in debug mode */
|
||||
setbits_le32(DBGMCU_APB4FZ1, DBGMCU_APB4FZ1_IWDG2);
|
||||
/*
|
||||
* Freeze IWDG2 if Cortex-A7 is in debug mode
|
||||
* done in TF-A for TRUSTED boot and
|
||||
* DBGMCU access is controlled by BSEC_DENABLE.DBGSWENABLE
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_TFABOOT) && bsec_dbgswenable())
|
||||
setbits_le32(DBGMCU_APB4FZ1, DBGMCU_APB4FZ1_IWDG2);
|
||||
}
|
||||
#endif /* !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) */
|
||||
|
||||
|
@ -276,9 +282,17 @@ void enable_caches(void)
|
|||
|
||||
static u32 read_idc(void)
|
||||
{
|
||||
setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
|
||||
/* DBGMCU access is controlled by BSEC_DENABLE.DBGSWENABLE */
|
||||
if (bsec_dbgswenable()) {
|
||||
setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
|
||||
|
||||
return readl(DBGMCU_IDC);
|
||||
return readl(DBGMCU_IDC);
|
||||
}
|
||||
|
||||
if (CONFIG_IS_ENABLED(STM32MP15x))
|
||||
return CPU_DEV_STM32MP15; /* STM32MP15x and unknown revision */
|
||||
else
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
u32 get_cpu_dev(void)
|
||||
|
|
7
arch/arm/mach-stm32mp/include/mach/bsec.h
Normal file
7
arch/arm/mach-stm32mp/include/mach/bsec.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2020, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
/* check self hosted debug status = BSEC_DENABLE.DBGSWENABLE */
|
||||
bool bsec_dbgswenable(void);
|
|
@ -48,3 +48,6 @@ void get_soc_name(char name[SOC_NAME_SIZE]);
|
|||
u32 get_bootmode(void);
|
||||
|
||||
int setup_mac_address(void);
|
||||
|
||||
/* board power management : configure vddcore according OPP */
|
||||
void board_vddcore_init(u32 voltage_mv);
|
||||
|
|
|
@ -3,11 +3,7 @@
|
|||
# Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
||||
#
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
obj-y += ../../st/stm32mp1/spl.o
|
||||
endif
|
||||
|
||||
obj-y += ../../st/stm32mp1/board.o board.o
|
||||
obj-y += ../../st/common/stpmic1.o board.o
|
||||
|
||||
obj-$(CONFIG_SYS_MTDPARTS_RUNTIME) += ../../st/common/stm32mp_mtdparts.o
|
||||
obj-$(CONFIG_SET_DFU_ALT_INFO) += ../../st/common/stm32mp_dfu.o
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <usb.h>
|
||||
#include <usb/dwc2_udc.h>
|
||||
#include <watchdog.h>
|
||||
#include "../../st/common/stpmic1.h"
|
||||
|
||||
/* SYSCFG registers */
|
||||
#define SYSCFG_BOOTR 0x00
|
||||
|
@ -139,6 +140,7 @@ int checkboard(void)
|
|||
static u8 brdcode __section("data");
|
||||
static u8 ddr3code __section("data");
|
||||
static u8 somcode __section("data");
|
||||
static u32 opp_voltage_mv __section(".data");
|
||||
|
||||
static void board_get_coding_straps(void)
|
||||
{
|
||||
|
@ -196,8 +198,16 @@ int board_stm32mp1_ddr_config_name_match(struct udevice *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
void board_vddcore_init(u32 voltage_mv)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_SPL_BUILD))
|
||||
opp_voltage_mv = voltage_mv;
|
||||
}
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_SPL_BUILD))
|
||||
stpmic1_init(opp_voltage_mv);
|
||||
board_get_coding_straps();
|
||||
|
||||
return 0;
|
||||
|
@ -513,17 +523,11 @@ static void board_init_fmc2(void)
|
|||
/* 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);
|
||||
}
|
||||
if (CONFIG_IS_ENABLED(DM_GPIO_HOG))
|
||||
gpio_hog_probe_all();
|
||||
|
||||
board_key_check();
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ config MTDPARTS_NOR0_BOOT
|
|||
|
||||
config MTDPARTS_NOR0_TEE
|
||||
string "mtd tee partitions for nor0"
|
||||
default "256k(teeh),256k(teed),256k(teex)"
|
||||
default "256k(teeh),512k(teed),256k(teex)"
|
||||
depends on SYS_MTDPARTS_RUNTIME && ARCH_STM32MP
|
||||
help
|
||||
This define the tee partitions added in mtparts dynamically
|
||||
|
@ -69,3 +69,10 @@ config DFU_ALT_RAM0
|
|||
depends on ARCH_STM32MP && SET_DFU_ALT_INFO
|
||||
help
|
||||
This defines the partitions of ram used to build dfu dynamically.
|
||||
|
||||
config TYPEC_STUSB160X
|
||||
tristate "STMicroelectronics STUSB160X Type-C controller driver"
|
||||
depends on DM_I2C
|
||||
help
|
||||
Say Y if your system has STMicroelectronics STUSB160X Type-C port
|
||||
controller.
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_CMD_STBOARD) += cmd_stboard.o
|
||||
obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o
|
||||
|
||||
ifeq ($(CONFIG_ARCH_STM32MP),y)
|
||||
obj-$(CONFIG_SYS_MTDPARTS_RUNTIME) += stm32mp_mtdparts.o
|
||||
obj-$(CONFIG_SET_DFU_ALT_INFO) += stm32mp_dfu.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o
|
||||
|
|
216
board/st/common/stpmic1.c
Normal file
216
board/st/common/stpmic1.c
Normal file
|
@ -0,0 +1,216 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2020, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/ddr.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/stpmic1.h>
|
||||
|
||||
int board_ddr_power_init(enum ddr_type ddr_type)
|
||||
{
|
||||
struct udevice *dev;
|
||||
bool buck3_at_1800000v = false;
|
||||
int ret;
|
||||
u32 buck2;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_PMIC,
|
||||
DM_GET_DRIVER(pmic_stpmic1), &dev);
|
||||
if (ret)
|
||||
/* No PMIC on board */
|
||||
return 0;
|
||||
|
||||
switch (ddr_type) {
|
||||
case STM32MP_DDR3:
|
||||
/* VTT = Set LDO3 to sync mode */
|
||||
ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= ~STPMIC1_LDO3_MODE;
|
||||
ret &= ~STPMIC1_LDO12356_VOUT_MASK;
|
||||
ret |= STPMIC1_LDO_VOUT(STPMIC1_LDO3_DDR_SEL);
|
||||
|
||||
ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
|
||||
ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* VDD_DDR = Set BUCK2 to 1.35V */
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
|
||||
STPMIC1_BUCK_VOUT_MASK,
|
||||
STPMIC1_BUCK2_1350000V);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Enable VDD_DDR = BUCK2 */
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
|
||||
STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
/* Enable VREF */
|
||||
ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR,
|
||||
STPMIC1_VREF_ENA, STPMIC1_VREF_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
/* Enable VTT = LDO3 */
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
|
||||
STPMIC1_LDO_ENA, STPMIC1_LDO_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
break;
|
||||
|
||||
case STM32MP_LPDDR2_16:
|
||||
case STM32MP_LPDDR2_32:
|
||||
case STM32MP_LPDDR3_16:
|
||||
case STM32MP_LPDDR3_32:
|
||||
/*
|
||||
* configure VDD_DDR1 = LDO3
|
||||
* Set LDO3 to 1.8V
|
||||
* + bypass mode if BUCK3 = 1.8V
|
||||
* + normal mode if BUCK3 != 1.8V
|
||||
*/
|
||||
ret = pmic_reg_read(dev,
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK3));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret & STPMIC1_BUCK3_1800000V) == STPMIC1_BUCK3_1800000V)
|
||||
buck3_at_1800000v = true;
|
||||
|
||||
ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= ~STPMIC1_LDO3_MODE;
|
||||
ret &= ~STPMIC1_LDO12356_VOUT_MASK;
|
||||
ret |= STPMIC1_LDO3_1800000;
|
||||
if (buck3_at_1800000v)
|
||||
ret |= STPMIC1_LDO3_MODE;
|
||||
|
||||
ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
|
||||
ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* VDD_DDR2 : Set BUCK2 to 1.2V (16bits) or 1.25V (32 bits)*/
|
||||
switch (ddr_type) {
|
||||
case STM32MP_LPDDR2_32:
|
||||
case STM32MP_LPDDR3_32:
|
||||
buck2 = STPMIC1_BUCK2_1250000V;
|
||||
break;
|
||||
default:
|
||||
case STM32MP_LPDDR2_16:
|
||||
case STM32MP_LPDDR3_16:
|
||||
buck2 = STPMIC1_BUCK2_1200000V;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
|
||||
STPMIC1_BUCK_VOUT_MASK,
|
||||
buck2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Enable VDD_DDR1 = LDO3 */
|
||||
ret = pmic_clrsetbits(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
|
||||
STPMIC1_LDO_ENA, STPMIC1_LDO_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
/* Enable VDD_DDR2 =BUCK2 */
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
|
||||
STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
/* Enable VREF */
|
||||
ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR,
|
||||
STPMIC1_VREF_ENA, STPMIC1_VREF_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stmpic_buck1_set(struct udevice *dev, u32 voltage_mv)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
/* VDDCORE= STMPCI1 BUCK1 ramp=+25mV, 5 => 725mV, 36 => 1500mV */
|
||||
value = ((voltage_mv - 725) / 25) + 5;
|
||||
if (value < 5)
|
||||
value = 5;
|
||||
if (value > 36)
|
||||
value = 36;
|
||||
|
||||
return pmic_clrsetbits(dev,
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK1),
|
||||
STPMIC1_BUCK_VOUT_MASK,
|
||||
STPMIC1_BUCK_VOUT(value));
|
||||
}
|
||||
|
||||
/* early init of PMIC */
|
||||
void stpmic1_init(u32 voltage_mv)
|
||||
{
|
||||
struct udevice *dev;
|
||||
|
||||
if (uclass_get_device_by_driver(UCLASS_PMIC,
|
||||
DM_GET_DRIVER(pmic_stpmic1), &dev))
|
||||
return;
|
||||
|
||||
/* update VDDCORE = BUCK1 */
|
||||
if (voltage_mv)
|
||||
stmpic_buck1_set(dev, voltage_mv);
|
||||
|
||||
/* Keep vdd on during the reset cycle */
|
||||
pmic_clrsetbits(dev,
|
||||
STPMIC1_BUCKS_MRST_CR,
|
||||
STPMIC1_MRST_BUCK(STPMIC1_BUCK3),
|
||||
STPMIC1_MRST_BUCK(STPMIC1_BUCK3));
|
||||
|
||||
/* Check if debug is enabled to program PMIC according to the bit */
|
||||
if (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_DEBUG_ON) {
|
||||
printf("Keep debug unit ON\n");
|
||||
|
||||
pmic_clrsetbits(dev, STPMIC1_BUCKS_MRST_CR,
|
||||
STPMIC1_MRST_BUCK_DEBUG,
|
||||
STPMIC1_MRST_BUCK_DEBUG);
|
||||
|
||||
if (STPMIC1_MRST_LDO_DEBUG)
|
||||
pmic_clrsetbits(dev, STPMIC1_LDOS_MRST_CR,
|
||||
STPMIC1_MRST_LDO_DEBUG,
|
||||
STPMIC1_MRST_LDO_DEBUG);
|
||||
}
|
||||
}
|
6
board/st/common/stpmic1.h
Normal file
6
board/st/common/stpmic1.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2020, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
void stpmic1_init(u32 voltage_mv);
|
46
board/st/common/stusb160x.c
Normal file
46
board/st/common/stusb160x.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* STMicroelectronics STUSB Type-C controller driver
|
||||
* based on Linux drivers/usb/typec/stusb160x.c
|
||||
*
|
||||
* Copyright (C) 2020, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
|
||||
/* REGISTER */
|
||||
#define STUSB160X_CC_CONNECTION_STATUS 0x0E
|
||||
|
||||
/* STUSB160X_CC_CONNECTION_STATUS bitfields */
|
||||
#define STUSB160X_CC_ATTACH BIT(0)
|
||||
|
||||
int stusb160x_cable_connected(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_I2C_GENERIC,
|
||||
DM_GET_DRIVER(stusb160x),
|
||||
&dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = dm_i2c_reg_read(dev, STUSB160X_CC_CONNECTION_STATUS);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
return ret & STUSB160X_CC_ATTACH;
|
||||
}
|
||||
|
||||
static const struct udevice_id stusb160x_ids[] = {
|
||||
{ .compatible = "st,stusb1600" },
|
||||
{}
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stusb160x) = {
|
||||
.name = "stusb160x",
|
||||
.id = UCLASS_I2C_GENERIC,
|
||||
.of_match = stusb160x_ids,
|
||||
};
|
10
board/st/common/stusb160x.h
Normal file
10
board/st/common/stusb160x.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020, STMicroelectronics
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_TYPEC_STUSB160X
|
||||
int stusb160x_cable_connected(void);
|
||||
#else
|
||||
int stusb160x_cable_connected(void) { return -ENODEV; }
|
||||
#endif
|
|
@ -8,5 +8,3 @@ obj-y += spl.o
|
|||
else
|
||||
obj-y += stm32mp1.o
|
||||
endif
|
||||
|
||||
obj-y += board.o
|
||||
|
|
|
@ -4,13 +4,9 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/ddr.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/stpmic1.h>
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_BOARD_INIT
|
||||
void board_debug_uart_init(void)
|
||||
|
@ -38,157 +34,3 @@ void board_debug_uart_init(void)
|
|||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PMIC_STPMIC1
|
||||
int board_ddr_power_init(enum ddr_type ddr_type)
|
||||
{
|
||||
struct udevice *dev;
|
||||
bool buck3_at_1800000v = false;
|
||||
int ret;
|
||||
u32 buck2;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_PMIC,
|
||||
DM_GET_DRIVER(pmic_stpmic1), &dev);
|
||||
if (ret)
|
||||
/* No PMIC on board */
|
||||
return 0;
|
||||
|
||||
switch (ddr_type) {
|
||||
case STM32MP_DDR3:
|
||||
/* VTT = Set LDO3 to sync mode */
|
||||
ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= ~STPMIC1_LDO3_MODE;
|
||||
ret &= ~STPMIC1_LDO12356_VOUT_MASK;
|
||||
ret |= STPMIC1_LDO_VOUT(STPMIC1_LDO3_DDR_SEL);
|
||||
|
||||
ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
|
||||
ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* VDD_DDR = Set BUCK2 to 1.35V */
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
|
||||
STPMIC1_BUCK_VOUT_MASK,
|
||||
STPMIC1_BUCK2_1350000V);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Enable VDD_DDR = BUCK2 */
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
|
||||
STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
/* Enable VREF */
|
||||
ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR,
|
||||
STPMIC1_VREF_ENA, STPMIC1_VREF_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
/* Enable VTT = LDO3 */
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
|
||||
STPMIC1_LDO_ENA, STPMIC1_LDO_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
break;
|
||||
|
||||
case STM32MP_LPDDR2_16:
|
||||
case STM32MP_LPDDR2_32:
|
||||
case STM32MP_LPDDR3_16:
|
||||
case STM32MP_LPDDR3_32:
|
||||
/*
|
||||
* configure VDD_DDR1 = LDO3
|
||||
* Set LDO3 to 1.8V
|
||||
* + bypass mode if BUCK3 = 1.8V
|
||||
* + normal mode if BUCK3 != 1.8V
|
||||
*/
|
||||
ret = pmic_reg_read(dev,
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK3));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret & STPMIC1_BUCK3_1800000V) == STPMIC1_BUCK3_1800000V)
|
||||
buck3_at_1800000v = true;
|
||||
|
||||
ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= ~STPMIC1_LDO3_MODE;
|
||||
ret &= ~STPMIC1_LDO12356_VOUT_MASK;
|
||||
ret |= STPMIC1_LDO3_1800000;
|
||||
if (buck3_at_1800000v)
|
||||
ret |= STPMIC1_LDO3_MODE;
|
||||
|
||||
ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
|
||||
ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* VDD_DDR2 : Set BUCK2 to 1.2V (16bits) or 1.25V (32 bits)*/
|
||||
switch (ddr_type) {
|
||||
case STM32MP_LPDDR2_32:
|
||||
case STM32MP_LPDDR3_32:
|
||||
buck2 = STPMIC1_BUCK2_1250000V;
|
||||
break;
|
||||
default:
|
||||
case STM32MP_LPDDR2_16:
|
||||
case STM32MP_LPDDR3_16:
|
||||
buck2 = STPMIC1_BUCK2_1200000V;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
|
||||
STPMIC1_BUCK_VOUT_MASK,
|
||||
buck2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Enable VDD_DDR1 = LDO3 */
|
||||
ret = pmic_clrsetbits(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
|
||||
STPMIC1_LDO_ENA, STPMIC1_LDO_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
/* Enable VDD_DDR2 =BUCK2 */
|
||||
ret = pmic_clrsetbits(dev,
|
||||
STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
|
||||
STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
/* Enable VREF */
|
||||
ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR,
|
||||
STPMIC1_VREF_ENA, STPMIC1_VREF_ENA);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -5,41 +5,51 @@
|
|||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <spl.h>
|
||||
#include <dm.h>
|
||||
#include <ram.h>
|
||||
#include <init.h>
|
||||
#include <asm/io.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/stpmic1.h>
|
||||
#include <asm/arch/ddr.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include "../common/stpmic1.h"
|
||||
|
||||
void spl_board_init(void)
|
||||
/* board early initialisation in board_f: need to use global variable */
|
||||
static u32 opp_voltage_mv __section(".data");
|
||||
|
||||
void board_vddcore_init(u32 voltage_mv)
|
||||
{
|
||||
/* Keep vdd on during the reset cycle */
|
||||
#if defined(CONFIG_PMIC_STPMIC1) && defined(CONFIG_SPL_POWER_SUPPORT)
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
if (IS_ENABLED(CONFIG_PMIC_STPMIC1) && CONFIG_IS_ENABLED(POWER_SUPPORT))
|
||||
opp_voltage_mv = voltage_mv;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_PMIC,
|
||||
DM_GET_DRIVER(pmic_stpmic1), &dev);
|
||||
if (!ret)
|
||||
pmic_clrsetbits(dev,
|
||||
STPMIC1_BUCKS_MRST_CR,
|
||||
STPMIC1_MRST_BUCK(STPMIC1_BUCK3),
|
||||
STPMIC1_MRST_BUCK(STPMIC1_BUCK3));
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_PMIC_STPMIC1) && CONFIG_IS_ENABLED(POWER_SUPPORT))
|
||||
stpmic1_init(opp_voltage_mv);
|
||||
|
||||
/* Check if debug is enabled to program PMIC according to the bit */
|
||||
if ((readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_DEBUG_ON) && !ret) {
|
||||
printf("Keep debug unit ON\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pmic_clrsetbits(dev, STPMIC1_BUCKS_MRST_CR,
|
||||
STPMIC1_MRST_BUCK_DEBUG,
|
||||
STPMIC1_MRST_BUCK_DEBUG);
|
||||
#ifdef CONFIG_DEBUG_UART_BOARD_INIT
|
||||
void board_debug_uart_init(void)
|
||||
{
|
||||
#if (CONFIG_DEBUG_UART_BASE == STM32_UART4_BASE)
|
||||
|
||||
#define RCC_MP_APB1ENSETR (STM32_RCC_BASE + 0x0A00)
|
||||
#define RCC_MP_AHB4ENSETR (STM32_RCC_BASE + 0x0A28)
|
||||
|
||||
/* UART4 clock enable */
|
||||
setbits_le32(RCC_MP_APB1ENSETR, BIT(16));
|
||||
|
||||
#define GPIOG_BASE 0x50008000
|
||||
/* GPIOG clock enable */
|
||||
writel(BIT(6), RCC_MP_AHB4ENSETR);
|
||||
/* GPIO configuration for ST boards: Uart4 TX = G11 */
|
||||
writel(0xffbfffff, GPIOG_BASE + 0x00);
|
||||
writel(0x00006000, GPIOG_BASE + 0x24);
|
||||
#else
|
||||
|
||||
#error("CONFIG_DEBUG_UART_BASE: not supported value")
|
||||
|
||||
if (STPMIC1_MRST_LDO_DEBUG)
|
||||
pmic_clrsetbits(dev, STPMIC1_LDOS_MRST_CR,
|
||||
STPMIC1_MRST_LDO_DEBUG,
|
||||
STPMIC1_MRST_LDO_DEBUG);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#include <power/regulator.h>
|
||||
#include <usb/dwc2_udc.h>
|
||||
|
||||
#include "../../st/common/stusb160x.h"
|
||||
|
||||
/* SYSCFG registers */
|
||||
#define SYSCFG_BOOTR 0x00
|
||||
#define SYSCFG_PMCSETR 0x04
|
||||
|
@ -84,6 +86,12 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
#define USB_START_LOW_THRESHOLD_UV 1230000
|
||||
#define USB_START_HIGH_THRESHOLD_UV 2150000
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
/* nothing to do, only used in SPL */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int checkboard(void)
|
||||
{
|
||||
int ret;
|
||||
|
@ -175,64 +183,16 @@ static void board_key_check(void)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
|
||||
|
||||
/* STMicroelectronics STUSB1600 Type-C controller */
|
||||
#define STUSB1600_CC_CONNECTION_STATUS 0x0E
|
||||
|
||||
/* STUSB1600_CC_CONNECTION_STATUS bitfields */
|
||||
#define STUSB1600_CC_ATTACH BIT(0)
|
||||
|
||||
static int stusb1600_init(struct udevice **dev_stusb1600)
|
||||
{
|
||||
ofnode node;
|
||||
struct udevice *dev, *bus;
|
||||
int ret;
|
||||
u32 chip_addr;
|
||||
|
||||
*dev_stusb1600 = NULL;
|
||||
|
||||
/* if node stusb1600 is present, means DK1 or DK2 board */
|
||||
node = ofnode_by_compatible(ofnode_null(), "st,stusb1600");
|
||||
if (!ofnode_valid(node))
|
||||
return -ENODEV;
|
||||
|
||||
ret = ofnode_read_u32(node, "reg", &chip_addr);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
ret = uclass_get_device_by_ofnode(UCLASS_I2C, ofnode_get_parent(node),
|
||||
&bus);
|
||||
if (ret) {
|
||||
printf("bus for stusb1600 not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = dm_i2c_probe(bus, chip_addr, 0, &dev);
|
||||
if (!ret)
|
||||
*dev_stusb1600 = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stusb1600_cable_connected(struct udevice *dev)
|
||||
{
|
||||
u8 status;
|
||||
|
||||
if (dm_i2c_read(dev, STUSB1600_CC_CONNECTION_STATUS, &status, 1))
|
||||
return 0;
|
||||
|
||||
return status & STUSB1600_CC_ATTACH;
|
||||
}
|
||||
|
||||
#include <usb/dwc2_udc.h>
|
||||
int g_dnl_board_usb_cable_connected(void)
|
||||
{
|
||||
struct udevice *stusb1600;
|
||||
struct udevice *dwc2_udc_otg;
|
||||
int ret;
|
||||
|
||||
if (!stusb1600_init(&stusb1600))
|
||||
return stusb1600_cable_connected(stusb1600);
|
||||
/* if typec stusb160x is present, means DK1 or DK2 board */
|
||||
ret = stusb160x_cable_connected();
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC,
|
||||
DM_GET_DRIVER(dwc2_udc_otg),
|
||||
|
@ -664,17 +624,11 @@ static void board_ev1_init(void)
|
|||
/* 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);
|
||||
}
|
||||
if (CONFIG_IS_ENABLED(DM_GPIO_HOG))
|
||||
gpio_hog_probe_all();
|
||||
|
||||
board_key_check();
|
||||
|
||||
|
|
|
@ -1265,7 +1265,7 @@ static int do_env_info(struct cmd_tbl *cmdtp, int flag,
|
|||
|
||||
/* evaluate whether environment can be persisted */
|
||||
if (eval_flags & ENV_INFO_IS_PERSISTED) {
|
||||
#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
|
||||
#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
|
||||
printf("Environment can be persisted\n");
|
||||
eval_results |= ENV_INFO_IS_PERSISTED;
|
||||
#else
|
||||
|
|
|
@ -10,6 +10,7 @@ CONFIG_SPL_MMC_SUPPORT=y
|
|||
CONFIG_SPL=y
|
||||
CONFIG_TARGET_ST_STM32MP15x=y
|
||||
CONFIG_CMD_STM32PROG=y
|
||||
CONFIG_TYPEC_STUSB160X=y
|
||||
CONFIG_ENV_OFFSET_REDUND=0x2C0000
|
||||
CONFIG_SPL_SPI_FLASH_SUPPORT=y
|
||||
CONFIG_SPL_SPI_SUPPORT=y
|
||||
|
@ -18,6 +19,7 @@ CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
|
|||
CONFIG_DISTRO_DEFAULTS=y
|
||||
CONFIG_FIT=y
|
||||
CONFIG_BOOTCOMMAND="run bootcmd_stm32mp"
|
||||
CONFIG_BOARD_EARLY_INIT_F=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=3
|
||||
CONFIG_SPL_I2C_SUPPORT=y
|
||||
|
@ -29,6 +31,7 @@ CONFIG_SYS_PROMPT="STM32MP> "
|
|||
# CONFIG_CMD_ELF is not set
|
||||
# CONFIG_CMD_EXPORTENV is not set
|
||||
# CONFIG_CMD_IMPORTENV is not set
|
||||
CONFIG_CMD_ERASEENV=y
|
||||
CONFIG_CMD_MEMINFO=y
|
||||
CONFIG_CMD_MEMTEST=y
|
||||
CONFIG_SYS_MEMTEST_START=0xc0000000
|
||||
|
@ -75,6 +78,7 @@ CONFIG_FASTBOOT_BUF_SIZE=0x02000000
|
|||
CONFIG_FASTBOOT_USB_DEV=1
|
||||
CONFIG_FASTBOOT_FLASH=y
|
||||
CONFIG_FASTBOOT_FLASH_MMC_DEV=1
|
||||
CONFIG_GPIO_HOG=y
|
||||
CONFIG_DM_HWSPINLOCK=y
|
||||
CONFIG_HWSPINLOCK_STM32=y
|
||||
CONFIG_DM_I2C=y
|
||||
|
@ -142,5 +146,7 @@ CONFIG_VIDEO_STM32=y
|
|||
CONFIG_VIDEO_STM32_DSI=y
|
||||
CONFIG_VIDEO_STM32_MAX_XRES=1280
|
||||
CONFIG_VIDEO_STM32_MAX_YRES=800
|
||||
CONFIG_WDT=y
|
||||
CONFIG_WDT_STM32MP=y
|
||||
CONFIG_ERRNO_STR=y
|
||||
CONFIG_FDT_FIXUP_PARTITIONS=y
|
||||
|
|
|
@ -6,6 +6,7 @@ CONFIG_ENV_OFFSET=0x280000
|
|||
CONFIG_ENV_SECT_SIZE=0x40000
|
||||
CONFIG_TARGET_ST_STM32MP15x=y
|
||||
CONFIG_CMD_STM32PROG=y
|
||||
CONFIG_TYPEC_STUSB160X=y
|
||||
CONFIG_ENV_OFFSET_REDUND=0x2C0000
|
||||
CONFIG_DISTRO_DEFAULTS=y
|
||||
CONFIG_FIT=y
|
||||
|
@ -14,6 +15,7 @@ CONFIG_SYS_PROMPT="STM32MP> "
|
|||
# CONFIG_CMD_ELF is not set
|
||||
# CONFIG_CMD_EXPORTENV is not set
|
||||
# CONFIG_CMD_IMPORTENV is not set
|
||||
CONFIG_CMD_ERASEENV=y
|
||||
CONFIG_CMD_MEMINFO=y
|
||||
CONFIG_CMD_MEMTEST=y
|
||||
CONFIG_SYS_MEMTEST_START=0xc0000000
|
||||
|
@ -59,6 +61,7 @@ CONFIG_FASTBOOT_BUF_SIZE=0x02000000
|
|||
CONFIG_FASTBOOT_USB_DEV=1
|
||||
CONFIG_FASTBOOT_FLASH=y
|
||||
CONFIG_FASTBOOT_FLASH_MMC_DEV=1
|
||||
CONFIG_GPIO_HOG=y
|
||||
CONFIG_DM_HWSPINLOCK=y
|
||||
CONFIG_HWSPINLOCK_STM32=y
|
||||
CONFIG_DM_I2C=y
|
||||
|
@ -127,5 +130,7 @@ CONFIG_VIDEO_STM32=y
|
|||
CONFIG_VIDEO_STM32_DSI=y
|
||||
CONFIG_VIDEO_STM32_MAX_XRES=1280
|
||||
CONFIG_VIDEO_STM32_MAX_YRES=800
|
||||
CONFIG_WDT=y
|
||||
CONFIG_WDT_STM32MP=y
|
||||
CONFIG_ERRNO_STR=y
|
||||
CONFIG_FDT_FIXUP_PARTITIONS=y
|
||||
|
|
|
@ -87,6 +87,10 @@ Optional Properties:
|
|||
are listed with associated reg 0 to 3.
|
||||
PLLx is off when the associated node is absent or deactivated.
|
||||
|
||||
For PLL1, when the node is absent, the frequency of the OPP node is used
|
||||
to compute the PLL setting (see compatible "operating-points-v2" in
|
||||
opp/opp.txt for details).
|
||||
|
||||
Here are the available properties for each PLL node:
|
||||
- compatible: should be "st,stm32mp1-pll"
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
#include <dt-bindings/clock/stm32mp1-clksrc.h>
|
||||
|
||||
|
@ -644,8 +645,18 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
|
|||
};
|
||||
|
||||
#ifdef STM32MP1_CLOCK_TREE_INIT
|
||||
|
||||
/* define characteristic of PLL according type */
|
||||
#define DIVM_MIN 0
|
||||
#define DIVM_MAX 63
|
||||
#define DIVN_MIN 24
|
||||
#define DIVP_MIN 0
|
||||
#define DIVP_MAX 127
|
||||
#define FRAC_MAX 8192
|
||||
|
||||
#define PLL1600_VCO_MIN 800000000
|
||||
#define PLL1600_VCO_MAX 1600000000
|
||||
|
||||
static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
|
||||
[PLL_800] = {
|
||||
.refclk_min = 4,
|
||||
|
@ -1190,6 +1201,213 @@ static ulong stm32mp1_clk_get_rate(struct clk *clk)
|
|||
}
|
||||
|
||||
#ifdef STM32MP1_CLOCK_TREE_INIT
|
||||
|
||||
bool stm32mp1_supports_opp(u32 opp_id, u32 cpu_type)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
switch (opp_id) {
|
||||
case 1:
|
||||
case 2:
|
||||
id = opp_id;
|
||||
break;
|
||||
default:
|
||||
id = 1; /* default value */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cpu_type) {
|
||||
case CPU_STM32MP157Fxx:
|
||||
case CPU_STM32MP157Dxx:
|
||||
case CPU_STM32MP153Fxx:
|
||||
case CPU_STM32MP153Dxx:
|
||||
case CPU_STM32MP151Fxx:
|
||||
case CPU_STM32MP151Dxx:
|
||||
return true;
|
||||
default:
|
||||
return id == 1;
|
||||
}
|
||||
}
|
||||
|
||||
__weak void board_vddcore_init(u32 voltage_mv)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* gets OPP parameters (frequency in KHz and voltage in mV) from
|
||||
* an OPP table subnode. Platform HW support capabilities are also checked.
|
||||
* Returns 0 on success and a negative FDT error code on failure.
|
||||
*/
|
||||
static int stm32mp1_get_opp(u32 cpu_type, ofnode subnode,
|
||||
u32 *freq_khz, u32 *voltage_mv)
|
||||
{
|
||||
u32 opp_hw;
|
||||
u64 read_freq_64;
|
||||
u32 read_voltage_32;
|
||||
|
||||
*freq_khz = 0;
|
||||
*voltage_mv = 0;
|
||||
|
||||
opp_hw = ofnode_read_u32_default(subnode, "opp-supported-hw", 0);
|
||||
if (opp_hw)
|
||||
if (!stm32mp1_supports_opp(opp_hw, cpu_type))
|
||||
return -FDT_ERR_BADVALUE;
|
||||
|
||||
read_freq_64 = ofnode_read_u64_default(subnode, "opp-hz", 0) /
|
||||
1000ULL;
|
||||
read_voltage_32 = ofnode_read_u32_default(subnode, "opp-microvolt", 0) /
|
||||
1000U;
|
||||
|
||||
if (!read_voltage_32 || !read_freq_64)
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
|
||||
/* Frequency value expressed in KHz must fit on 32 bits */
|
||||
if (read_freq_64 > U32_MAX)
|
||||
return -FDT_ERR_BADVALUE;
|
||||
|
||||
/* Millivolt value must fit on 16 bits */
|
||||
if (read_voltage_32 > U16_MAX)
|
||||
return -FDT_ERR_BADVALUE;
|
||||
|
||||
*freq_khz = (u32)read_freq_64;
|
||||
*voltage_mv = read_voltage_32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* parses OPP table in DT and finds the parameters for the
|
||||
* highest frequency supported by the HW platform.
|
||||
* Returns 0 on success and a negative FDT error code on failure.
|
||||
*/
|
||||
int stm32mp1_get_max_opp_freq(struct stm32mp1_clk_priv *priv, u64 *freq_hz)
|
||||
{
|
||||
ofnode node, subnode;
|
||||
int ret;
|
||||
u32 freq = 0U, voltage = 0U;
|
||||
u32 cpu_type = get_cpu_type();
|
||||
|
||||
node = ofnode_by_compatible(ofnode_null(), "operating-points-v2");
|
||||
if (!ofnode_valid(node))
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
|
||||
ofnode_for_each_subnode(subnode, node) {
|
||||
unsigned int read_freq;
|
||||
unsigned int read_voltage;
|
||||
|
||||
ret = stm32mp1_get_opp(cpu_type, subnode,
|
||||
&read_freq, &read_voltage);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
if (read_freq > freq) {
|
||||
freq = read_freq;
|
||||
voltage = read_voltage;
|
||||
}
|
||||
}
|
||||
|
||||
if (!freq || !voltage)
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
|
||||
*freq_hz = (u64)1000U * freq;
|
||||
board_vddcore_init(voltage);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32mp1_pll1_opp(struct stm32mp1_clk_priv *priv, int clksrc,
|
||||
u32 *pllcfg, u32 *fracv)
|
||||
{
|
||||
u32 post_divm;
|
||||
u32 input_freq;
|
||||
u64 output_freq;
|
||||
u64 freq;
|
||||
u64 vco;
|
||||
u32 divm, divn, divp, frac;
|
||||
int i, ret;
|
||||
u32 diff;
|
||||
u32 best_diff = U32_MAX;
|
||||
|
||||
/* PLL1 is 1600 */
|
||||
const u32 DIVN_MAX = stm32mp1_pll[PLL_1600].divn_max;
|
||||
const u32 POST_DIVM_MIN = stm32mp1_pll[PLL_1600].refclk_min * 1000000U;
|
||||
const u32 POST_DIVM_MAX = stm32mp1_pll[PLL_1600].refclk_max * 1000000U;
|
||||
|
||||
ret = stm32mp1_get_max_opp_freq(priv, &output_freq);
|
||||
if (ret) {
|
||||
debug("PLL1 OPP configuration not found (%d).\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (clksrc) {
|
||||
case CLK_PLL12_HSI:
|
||||
input_freq = stm32mp1_clk_get_fixed(priv, _HSI);
|
||||
break;
|
||||
case CLK_PLL12_HSE:
|
||||
input_freq = stm32mp1_clk_get_fixed(priv, _HSE);
|
||||
break;
|
||||
default:
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
/* Following parameters have always the same value */
|
||||
pllcfg[PLLCFG_Q] = 0;
|
||||
pllcfg[PLLCFG_R] = 0;
|
||||
pllcfg[PLLCFG_O] = PQR(1, 0, 0);
|
||||
|
||||
for (divm = DIVM_MAX; divm >= DIVM_MIN; divm--) {
|
||||
post_divm = (u32)(input_freq / (divm + 1));
|
||||
if (post_divm < POST_DIVM_MIN || post_divm > POST_DIVM_MAX)
|
||||
continue;
|
||||
|
||||
for (divp = DIVP_MIN; divp <= DIVP_MAX; divp++) {
|
||||
freq = output_freq * (divm + 1) * (divp + 1);
|
||||
divn = (u32)((freq / input_freq) - 1);
|
||||
if (divn < DIVN_MIN || divn > DIVN_MAX)
|
||||
continue;
|
||||
|
||||
frac = (u32)(((freq * FRAC_MAX) / input_freq) -
|
||||
((divn + 1) * FRAC_MAX));
|
||||
/* 2 loops to refine the fractional part */
|
||||
for (i = 2; i != 0; i--) {
|
||||
if (frac > FRAC_MAX)
|
||||
break;
|
||||
|
||||
vco = (post_divm * (divn + 1)) +
|
||||
((post_divm * (u64)frac) /
|
||||
FRAC_MAX);
|
||||
if (vco < (PLL1600_VCO_MIN / 2) ||
|
||||
vco > (PLL1600_VCO_MAX / 2)) {
|
||||
frac++;
|
||||
continue;
|
||||
}
|
||||
freq = vco / (divp + 1);
|
||||
if (output_freq < freq)
|
||||
diff = (u32)(freq - output_freq);
|
||||
else
|
||||
diff = (u32)(output_freq - freq);
|
||||
if (diff < best_diff) {
|
||||
pllcfg[PLLCFG_M] = divm;
|
||||
pllcfg[PLLCFG_N] = divn;
|
||||
pllcfg[PLLCFG_P] = divp;
|
||||
*fracv = frac;
|
||||
|
||||
if (diff == 0)
|
||||
return 0;
|
||||
|
||||
best_diff = diff;
|
||||
}
|
||||
frac++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best_diff == U32_MAX)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stm32mp1_ls_osc_set(int enable, fdt_addr_t rcc, u32 offset,
|
||||
u32 mask_on)
|
||||
{
|
||||
|
@ -1661,9 +1879,12 @@ static int stm32mp1_clktree(struct udevice *dev)
|
|||
unsigned int clksrc[CLKSRC_NB];
|
||||
unsigned int clkdiv[CLKDIV_NB];
|
||||
unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
|
||||
ofnode plloff[_PLL_NB];
|
||||
int ret, len;
|
||||
uint i;
|
||||
unsigned int pllfracv[_PLL_NB];
|
||||
unsigned int pllcsg[_PLL_NB][PLLCSG_NB];
|
||||
bool pllcfg_valid[_PLL_NB];
|
||||
bool pllcsg_set[_PLL_NB];
|
||||
int ret;
|
||||
int i, len;
|
||||
int lse_css = 0;
|
||||
const u32 *pkcs_cell;
|
||||
|
||||
|
@ -1683,16 +1904,43 @@ static int stm32mp1_clktree(struct udevice *dev)
|
|||
/* check mandatory field in each pll */
|
||||
for (i = 0; i < _PLL_NB; i++) {
|
||||
char name[12];
|
||||
ofnode node;
|
||||
|
||||
sprintf(name, "st,pll@%d", i);
|
||||
plloff[i] = dev_read_subnode(dev, name);
|
||||
if (!ofnode_valid(plloff[i]))
|
||||
continue;
|
||||
ret = ofnode_read_u32_array(plloff[i], "cfg",
|
||||
pllcfg[i], PLLCFG_NB);
|
||||
if (ret < 0) {
|
||||
debug("field cfg invalid: error %d\n", ret);
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
node = dev_read_subnode(dev, name);
|
||||
pllcfg_valid[i] = ofnode_valid(node);
|
||||
pllcsg_set[i] = false;
|
||||
if (pllcfg_valid[i]) {
|
||||
debug("DT for PLL %d @ %s\n", i, name);
|
||||
ret = ofnode_read_u32_array(node, "cfg",
|
||||
pllcfg[i], PLLCFG_NB);
|
||||
if (ret < 0) {
|
||||
debug("field cfg invalid: error %d\n", ret);
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
pllfracv[i] = ofnode_read_u32_default(node, "frac", 0);
|
||||
|
||||
ret = ofnode_read_u32_array(node, "csg", pllcsg[i],
|
||||
PLLCSG_NB);
|
||||
if (!ret) {
|
||||
pllcsg_set[i] = true;
|
||||
} else if (ret != -FDT_ERR_NOTFOUND) {
|
||||
debug("invalid csg node for pll@%d res=%d\n",
|
||||
i, ret);
|
||||
return ret;
|
||||
}
|
||||
} else if (i == _PLL1) {
|
||||
/* use OPP for PLL1 for A7 CPU */
|
||||
debug("DT for PLL %d with OPP\n", i);
|
||||
ret = stm32mp1_pll1_opp(priv,
|
||||
clksrc[CLKSRC_PLL12],
|
||||
pllcfg[i],
|
||||
&pllfracv[i]);
|
||||
if (ret) {
|
||||
debug("PLL %d with OPP error = %d\n", i, ret);
|
||||
return ret;
|
||||
}
|
||||
pllcfg_valid[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1778,29 +2026,18 @@ static int stm32mp1_clktree(struct udevice *dev)
|
|||
/* configure and start PLLs */
|
||||
debug("configure PLLs\n");
|
||||
for (i = 0; i < _PLL_NB; i++) {
|
||||
u32 fracv;
|
||||
u32 csg[PLLCSG_NB];
|
||||
|
||||
debug("configure PLL %d @ %d\n", i,
|
||||
ofnode_to_offset(plloff[i]));
|
||||
if (!ofnode_valid(plloff[i]))
|
||||
if (!pllcfg_valid[i])
|
||||
continue;
|
||||
|
||||
fracv = ofnode_read_u32_default(plloff[i], "frac", 0);
|
||||
pll_config(priv, i, pllcfg[i], fracv);
|
||||
ret = ofnode_read_u32_array(plloff[i], "csg", csg, PLLCSG_NB);
|
||||
if (!ret) {
|
||||
pll_csg(priv, i, csg);
|
||||
} else if (ret != -FDT_ERR_NOTFOUND) {
|
||||
debug("invalid csg node for pll@%d res=%d\n", i, ret);
|
||||
return ret;
|
||||
}
|
||||
debug("configure PLL %d\n", i);
|
||||
pll_config(priv, i, pllcfg[i], pllfracv[i]);
|
||||
if (pllcsg_set[i])
|
||||
pll_csg(priv, i, pllcsg[i]);
|
||||
pll_start(priv, i);
|
||||
}
|
||||
|
||||
/* wait and start PLLs ouptut when ready */
|
||||
for (i = 0; i < _PLL_NB; i++) {
|
||||
if (!ofnode_valid(plloff[i]))
|
||||
if (!pllcfg_valid[i])
|
||||
continue;
|
||||
debug("output PLL %d\n", i);
|
||||
pll_output(priv, i, pllcfg[i][PLLCFG_O]);
|
||||
|
@ -2050,6 +2287,8 @@ static int stm32mp1_clk_probe(struct udevice *dev)
|
|||
/* clock tree init is done only one time, before relocation */
|
||||
if (!(gd->flags & GD_FLG_RELOC))
|
||||
result = stm32mp1_clktree(dev);
|
||||
if (result)
|
||||
printf("clock tree initialization failed (%d)\n", result);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
|
|
|
@ -18,9 +18,65 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#define MODE_BITS(gpio_pin) (gpio_pin * 2)
|
||||
#define MODE_BITS(gpio_pin) ((gpio_pin) * 2)
|
||||
#define MODE_BITS_MASK 3
|
||||
#define BSRR_BIT(gpio_pin, value) BIT(gpio_pin + (value ? 0 : 16))
|
||||
#define BSRR_BIT(gpio_pin, value) BIT((gpio_pin) + (value ? 0 : 16))
|
||||
|
||||
#define PUPD_BITS(gpio_pin) ((gpio_pin) * 2)
|
||||
#define PUPD_MASK 3
|
||||
|
||||
#define OTYPE_BITS(gpio_pin) (gpio_pin)
|
||||
#define OTYPE_MSK 1
|
||||
|
||||
static void stm32_gpio_set_moder(struct stm32_gpio_regs *regs,
|
||||
int idx,
|
||||
int mode)
|
||||
{
|
||||
int bits_index;
|
||||
int mask;
|
||||
|
||||
bits_index = MODE_BITS(idx);
|
||||
mask = MODE_BITS_MASK << bits_index;
|
||||
|
||||
clrsetbits_le32(®s->moder, mask, mode << bits_index);
|
||||
}
|
||||
|
||||
static int stm32_gpio_get_moder(struct stm32_gpio_regs *regs, int idx)
|
||||
{
|
||||
return (readl(®s->moder) >> MODE_BITS(idx)) & MODE_BITS_MASK;
|
||||
}
|
||||
|
||||
static void stm32_gpio_set_otype(struct stm32_gpio_regs *regs,
|
||||
int idx,
|
||||
enum stm32_gpio_otype otype)
|
||||
{
|
||||
int bits;
|
||||
|
||||
bits = OTYPE_BITS(idx);
|
||||
clrsetbits_le32(®s->otyper, OTYPE_MSK << bits, otype << bits);
|
||||
}
|
||||
|
||||
static enum stm32_gpio_otype stm32_gpio_get_otype(struct stm32_gpio_regs *regs,
|
||||
int idx)
|
||||
{
|
||||
return (readl(®s->otyper) >> OTYPE_BITS(idx)) & OTYPE_MSK;
|
||||
}
|
||||
|
||||
static void stm32_gpio_set_pupd(struct stm32_gpio_regs *regs,
|
||||
int idx,
|
||||
enum stm32_gpio_pupd pupd)
|
||||
{
|
||||
int bits;
|
||||
|
||||
bits = PUPD_BITS(idx);
|
||||
clrsetbits_le32(®s->pupdr, PUPD_MASK << bits, pupd << bits);
|
||||
}
|
||||
|
||||
static enum stm32_gpio_pupd stm32_gpio_get_pupd(struct stm32_gpio_regs *regs,
|
||||
int idx)
|
||||
{
|
||||
return (readl(®s->pupdr) >> PUPD_BITS(idx)) & PUPD_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* convert gpio offset to gpio index taking into account gpio holes
|
||||
|
@ -47,18 +103,13 @@ static int stm32_gpio_direction_input(struct udevice *dev, unsigned offset)
|
|||
{
|
||||
struct stm32_gpio_priv *priv = dev_get_priv(dev);
|
||||
struct stm32_gpio_regs *regs = priv->regs;
|
||||
int bits_index;
|
||||
int mask;
|
||||
int idx;
|
||||
|
||||
idx = stm32_offset_to_index(dev, offset);
|
||||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
bits_index = MODE_BITS(idx);
|
||||
mask = MODE_BITS_MASK << bits_index;
|
||||
|
||||
clrsetbits_le32(®s->moder, mask, STM32_GPIO_MODE_IN << bits_index);
|
||||
stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_IN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -68,18 +119,13 @@ static int stm32_gpio_direction_output(struct udevice *dev, unsigned offset,
|
|||
{
|
||||
struct stm32_gpio_priv *priv = dev_get_priv(dev);
|
||||
struct stm32_gpio_regs *regs = priv->regs;
|
||||
int bits_index;
|
||||
int mask;
|
||||
int idx;
|
||||
|
||||
idx = stm32_offset_to_index(dev, offset);
|
||||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
bits_index = MODE_BITS(idx);
|
||||
mask = MODE_BITS_MASK << bits_index;
|
||||
|
||||
clrsetbits_le32(®s->moder, mask, STM32_GPIO_MODE_OUT << bits_index);
|
||||
stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT);
|
||||
|
||||
writel(BSRR_BIT(idx, value), ®s->bsrr);
|
||||
|
||||
|
@ -141,12 +187,87 @@ static int stm32_gpio_get_function(struct udevice *dev, unsigned int offset)
|
|||
return GPIOF_FUNC;
|
||||
}
|
||||
|
||||
static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
|
||||
ulong flags)
|
||||
{
|
||||
struct stm32_gpio_priv *priv = dev_get_priv(dev);
|
||||
struct stm32_gpio_regs *regs = priv->regs;
|
||||
int idx;
|
||||
|
||||
idx = stm32_offset_to_index(dev, offset);
|
||||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
if (flags & GPIOD_IS_OUT) {
|
||||
int value = GPIOD_FLAGS_OUTPUT(flags);
|
||||
|
||||
if (flags & GPIOD_OPEN_DRAIN)
|
||||
stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_OD);
|
||||
else
|
||||
stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_PP);
|
||||
stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT);
|
||||
writel(BSRR_BIT(idx, value), ®s->bsrr);
|
||||
|
||||
} else if (flags & GPIOD_IS_IN) {
|
||||
stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_IN);
|
||||
if (flags & GPIOD_PULL_UP)
|
||||
stm32_gpio_set_pupd(regs, idx, STM32_GPIO_PUPD_UP);
|
||||
else if (flags & GPIOD_PULL_DOWN)
|
||||
stm32_gpio_set_pupd(regs, idx, STM32_GPIO_PUPD_DOWN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
|
||||
ulong *flags)
|
||||
{
|
||||
struct stm32_gpio_priv *priv = dev_get_priv(dev);
|
||||
struct stm32_gpio_regs *regs = priv->regs;
|
||||
int idx;
|
||||
ulong dir_flags = 0;
|
||||
|
||||
idx = stm32_offset_to_index(dev, offset);
|
||||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
switch (stm32_gpio_get_moder(regs, idx)) {
|
||||
case STM32_GPIO_MODE_OUT:
|
||||
dir_flags |= GPIOD_IS_OUT;
|
||||
if (stm32_gpio_get_otype(regs, idx) == STM32_GPIO_OTYPE_OD)
|
||||
dir_flags |= GPIOD_OPEN_DRAIN;
|
||||
if (readl(®s->idr) & BIT(idx))
|
||||
dir_flags |= GPIOD_IS_OUT_ACTIVE;
|
||||
break;
|
||||
case STM32_GPIO_MODE_IN:
|
||||
dir_flags |= GPIOD_IS_IN;
|
||||
switch (stm32_gpio_get_pupd(regs, idx)) {
|
||||
case STM32_GPIO_PUPD_UP:
|
||||
dir_flags |= GPIOD_PULL_UP;
|
||||
break;
|
||||
case STM32_GPIO_PUPD_DOWN:
|
||||
dir_flags |= GPIOD_PULL_DOWN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*flags = dir_flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_gpio_ops gpio_stm32_ops = {
|
||||
.direction_input = stm32_gpio_direction_input,
|
||||
.direction_output = stm32_gpio_direction_output,
|
||||
.get_value = stm32_gpio_get_value,
|
||||
.set_value = stm32_gpio_set_value,
|
||||
.get_function = stm32_gpio_get_function,
|
||||
.set_dir_flags = stm32_gpio_set_dir_flags,
|
||||
.get_dir_flags = stm32_gpio_get_dir_flags,
|
||||
};
|
||||
|
||||
static int gpio_stm32_probe(struct udevice *dev)
|
||||
|
|
|
@ -2170,7 +2170,7 @@ static const struct udevice_id eqos_ids[] = {
|
|||
.data = (ulong)&eqos_tegra186_config
|
||||
},
|
||||
{
|
||||
.compatible = "snps,dwmac-4.20a",
|
||||
.compatible = "st,stm32mp1-dwmac",
|
||||
.data = (ulong)&eqos_stm32_config
|
||||
},
|
||||
{
|
||||
|
|
|
@ -74,17 +74,61 @@ 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)
|
||||
static int stmfx_read_reg(struct udevice *dev, u8 reg_base, uint offset)
|
||||
{
|
||||
u32 reg = STMFX_REG_GPIO_STATE + get_reg(offset);
|
||||
u8 reg = reg_base + get_reg(offset);
|
||||
u32 mask = get_mask(offset);
|
||||
int ret;
|
||||
|
||||
ret = stmfx_read(dev, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ret < 0 ? ret : !!(ret & mask);
|
||||
}
|
||||
|
||||
static int stmfx_write_reg(struct udevice *dev, u8 reg_base, uint offset,
|
||||
uint val)
|
||||
{
|
||||
u8 reg = reg_base + get_reg(offset);
|
||||
u32 mask = get_mask(offset);
|
||||
int ret;
|
||||
|
||||
ret = stmfx_read(dev, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = (ret & ~mask) | (val ? mask : 0);
|
||||
|
||||
return stmfx_write(dev, reg, ret);
|
||||
}
|
||||
|
||||
static int stmfx_conf_set_pupd(struct udevice *dev, unsigned int offset,
|
||||
uint pupd)
|
||||
{
|
||||
return stmfx_write_reg(dev, STMFX_REG_GPIO_PUPD, offset, pupd);
|
||||
}
|
||||
|
||||
static int stmfx_conf_get_pupd(struct udevice *dev, unsigned int offset)
|
||||
{
|
||||
return stmfx_read_reg(dev, STMFX_REG_GPIO_PUPD, offset);
|
||||
}
|
||||
|
||||
static int stmfx_conf_set_type(struct udevice *dev, unsigned int offset,
|
||||
uint type)
|
||||
{
|
||||
return stmfx_write_reg(dev, STMFX_REG_GPIO_TYPE, offset, type);
|
||||
}
|
||||
|
||||
static int stmfx_conf_get_type(struct udevice *dev, unsigned int offset)
|
||||
{
|
||||
return stmfx_read_reg(dev, STMFX_REG_GPIO_TYPE, offset);
|
||||
}
|
||||
|
||||
static int stmfx_gpio_get(struct udevice *dev, unsigned int offset)
|
||||
{
|
||||
return stmfx_read_reg(dev, STMFX_REG_GPIO_STATE, offset);
|
||||
}
|
||||
|
||||
static int stmfx_gpio_set(struct udevice *dev, unsigned int offset, int value)
|
||||
{
|
||||
u32 reg = value ? STMFX_REG_GPO_SET : STMFX_REG_GPO_CLR;
|
||||
|
@ -95,50 +139,103 @@ static int stmfx_gpio_set(struct udevice *dev, unsigned int offset, int value)
|
|||
|
||||
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);
|
||||
int ret = stmfx_read_reg(dev, STMFX_REG_GPIO_DIR, offset);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* On stmfx, gpio pins direction is (0)input, (1)output. */
|
||||
|
||||
return ret & mask ? GPIOF_OUTPUT : GPIOF_INPUT;
|
||||
return ret ? 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);
|
||||
return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 0);
|
||||
}
|
||||
|
||||
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 = stmfx_gpio_set(dev, offset, value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 1);
|
||||
}
|
||||
|
||||
static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
|
||||
ulong flags)
|
||||
{
|
||||
int ret = -ENOTSUPP;
|
||||
|
||||
if (flags & GPIOD_IS_OUT) {
|
||||
if (flags & GPIOD_OPEN_SOURCE)
|
||||
return -ENOTSUPP;
|
||||
if (flags & GPIOD_OPEN_DRAIN)
|
||||
ret = stmfx_conf_set_type(dev, offset, 0);
|
||||
else /* PUSH-PULL */
|
||||
ret = stmfx_conf_set_type(dev, offset, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = stmfx_gpio_direction_output(dev, offset,
|
||||
GPIOD_FLAGS_OUTPUT(flags));
|
||||
} else if (flags & GPIOD_IS_IN) {
|
||||
ret = stmfx_gpio_direction_input(dev, offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (flags & GPIOD_PULL_UP) {
|
||||
ret = stmfx_conf_set_type(dev, offset, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = stmfx_conf_set_pupd(dev, offset, 1);
|
||||
} else if (flags & GPIOD_PULL_DOWN) {
|
||||
ret = stmfx_conf_set_type(dev, offset, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = stmfx_conf_set_pupd(dev, offset, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stmfx_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
|
||||
ulong *flags)
|
||||
{
|
||||
ulong dir_flags = 0;
|
||||
int ret;
|
||||
|
||||
ret = stmfx_gpio_set(dev, offset, value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (stmfx_gpio_get_function(dev, offset) == GPIOF_OUTPUT) {
|
||||
dir_flags |= GPIOD_IS_OUT;
|
||||
ret = stmfx_conf_get_type(dev, offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 0)
|
||||
dir_flags |= GPIOD_OPEN_DRAIN;
|
||||
/* 1 = push-pull (default), open source not supported */
|
||||
ret = stmfx_gpio_get(dev, offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret)
|
||||
dir_flags |= GPIOD_IS_OUT_ACTIVE;
|
||||
} else {
|
||||
dir_flags |= GPIOD_IS_IN;
|
||||
ret = stmfx_conf_get_type(dev, offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 1) {
|
||||
ret = stmfx_conf_get_pupd(dev, offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 1)
|
||||
dir_flags |= GPIOD_PULL_UP;
|
||||
else
|
||||
dir_flags |= GPIOD_PULL_DOWN;
|
||||
}
|
||||
}
|
||||
*flags = dir_flags;
|
||||
|
||||
ret = stmfx_read(dev, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return stmfx_write(dev, reg, ret | mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stmfx_gpio_probe(struct udevice *dev)
|
||||
|
@ -169,6 +266,8 @@ static const struct dm_gpio_ops stmfx_gpio_ops = {
|
|||
.get_function = stmfx_gpio_get_function,
|
||||
.direction_input = stmfx_gpio_direction_input,
|
||||
.direction_output = stmfx_gpio_direction_output,
|
||||
.set_dir_flags = stmfx_gpio_set_dir_flags,
|
||||
.get_dir_flags = stmfx_gpio_get_dir_flags,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stmfx_gpio) = {
|
||||
|
@ -190,36 +289,6 @@ static const struct pinconf_param stmfx_pinctrl_conf_params[] = {
|
|||
{ "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)
|
||||
{
|
||||
|
@ -235,22 +304,22 @@ static int stmfx_pinctrl_conf_set(struct udevice *dev, unsigned int pin,
|
|||
case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
||||
ret = stmfx_pinctrl_set_type(dev, pin, 0);
|
||||
ret = stmfx_conf_set_type(dev, pin, 0);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
ret = stmfx_pinctrl_set_type(dev, pin, 1);
|
||||
ret = stmfx_conf_set_type(dev, pin, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = stmfx_pinctrl_set_pupd(dev, pin, 0);
|
||||
ret = stmfx_conf_set_pupd(dev, pin, 0);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
ret = stmfx_pinctrl_set_type(dev, pin, 1);
|
||||
ret = stmfx_conf_set_type(dev, pin, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = stmfx_pinctrl_set_pupd(dev, pin, 1);
|
||||
ret = stmfx_conf_set_pupd(dev, pin, 1);
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
ret = stmfx_pinctrl_set_type(dev, pin, 1);
|
||||
ret = stmfx_conf_set_type(dev, pin, 1);
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
ret = stmfx_gpio_direction_output(plat->gpio, pin, arg);
|
||||
|
@ -289,6 +358,34 @@ static const char *stmfx_pinctrl_get_pin_name(struct udevice *dev,
|
|||
return pin_name;
|
||||
}
|
||||
|
||||
static const char *stmfx_pinctrl_get_pin_conf(struct udevice *dev,
|
||||
unsigned int pin, int func)
|
||||
{
|
||||
int pupd, type;
|
||||
|
||||
type = stmfx_conf_get_type(dev, pin);
|
||||
if (type < 0)
|
||||
return "";
|
||||
|
||||
if (func == GPIOF_OUTPUT) {
|
||||
if (type)
|
||||
return "drive-open-drain";
|
||||
else
|
||||
return ""; /* default: push-pull*/
|
||||
}
|
||||
if (!type)
|
||||
return ""; /* default: bias-disable*/
|
||||
|
||||
pupd = stmfx_conf_get_pupd(dev, pin);
|
||||
if (pupd < 0)
|
||||
return "";
|
||||
|
||||
if (pupd)
|
||||
return "bias-pull-up";
|
||||
else
|
||||
return "bias-pull-down";
|
||||
}
|
||||
|
||||
static int stmfx_pinctrl_get_pin_muxing(struct udevice *dev,
|
||||
unsigned int selector,
|
||||
char *buf, int size)
|
||||
|
@ -300,7 +397,9 @@ static int stmfx_pinctrl_get_pin_muxing(struct udevice *dev,
|
|||
if (func < 0)
|
||||
return func;
|
||||
|
||||
snprintf(buf, size, "%s", func == GPIOF_INPUT ? "input" : "output");
|
||||
snprintf(buf, size, "%s ", func == GPIOF_INPUT ? "input" : "output");
|
||||
|
||||
strncat(buf, stmfx_pinctrl_get_pin_conf(dev, selector, func), size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,17 @@ static const char * const pinmux_mode[PINMUX_MODE_COUNT] = {
|
|||
"alt function",
|
||||
};
|
||||
|
||||
static const char * const pinmux_output[] = {
|
||||
[STM32_GPIO_PUPD_NO] = "bias-disable",
|
||||
[STM32_GPIO_PUPD_UP] = "bias-pull-up",
|
||||
[STM32_GPIO_PUPD_DOWN] = "bias-pull-down",
|
||||
};
|
||||
|
||||
static const char * const pinmux_input[] = {
|
||||
[STM32_GPIO_OTYPE_PP] = "drive-push-pull",
|
||||
[STM32_GPIO_OTYPE_OD] = "drive-open-drain",
|
||||
};
|
||||
|
||||
static int stm32_pinctrl_get_af(struct udevice *dev, unsigned int offset)
|
||||
{
|
||||
struct stm32_gpio_priv *priv = dev_get_priv(dev);
|
||||
|
@ -182,10 +193,12 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
|
|||
int size)
|
||||
{
|
||||
struct udevice *gpio_dev;
|
||||
struct stm32_gpio_priv *priv;
|
||||
const char *label;
|
||||
int mode;
|
||||
int af_num;
|
||||
unsigned int gpio_idx;
|
||||
u32 pupd, otype;
|
||||
|
||||
/* look up for the bank which owns the requested pin */
|
||||
gpio_dev = stm32_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
|
||||
|
@ -194,9 +207,9 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
|
|||
return -ENODEV;
|
||||
|
||||
mode = gpio_get_raw_function(gpio_dev, gpio_idx, &label);
|
||||
|
||||
dev_dbg(dev, "selector = %d gpio_idx = %d mode = %d\n",
|
||||
selector, gpio_idx, mode);
|
||||
priv = dev_get_priv(gpio_dev);
|
||||
|
||||
|
||||
switch (mode) {
|
||||
|
@ -211,9 +224,17 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
|
|||
snprintf(buf, size, "%s %d", pinmux_mode[mode], af_num);
|
||||
break;
|
||||
case GPIOF_OUTPUT:
|
||||
pupd = (readl(&priv->regs->pupdr) >> (gpio_idx * 2)) &
|
||||
PUPD_MASK;
|
||||
snprintf(buf, size, "%s %s %s",
|
||||
pinmux_mode[mode], pinmux_output[pupd],
|
||||
label ? label : "");
|
||||
break;
|
||||
case GPIOF_INPUT:
|
||||
snprintf(buf, size, "%s %s",
|
||||
pinmux_mode[mode], label ? label : "");
|
||||
otype = (readl(&priv->regs->otyper) >> gpio_idx) & OTYPE_MSK;
|
||||
snprintf(buf, size, "%s %s %s",
|
||||
pinmux_mode[mode], pinmux_input[otype],
|
||||
label ? label : "");
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,8 +43,20 @@ static int stm32_vrefbuf_set_enable(struct udevice *dev, bool enable)
|
|||
u32 val;
|
||||
int ret;
|
||||
|
||||
clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_HIZ | STM32_ENVR,
|
||||
enable ? STM32_ENVR : STM32_HIZ);
|
||||
if (enable && !(readl(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR)) {
|
||||
/*
|
||||
* There maybe an overshoot:
|
||||
* - when disabling, then re-enabling vrefbuf too quickly
|
||||
* - or upon platform reset as external capacitor maybe slow
|
||||
* discharging (VREFBUF is HiZ at reset by default).
|
||||
* So force active discharge (HiZ=0) for 1ms before enabling.
|
||||
*/
|
||||
clrbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_HIZ);
|
||||
udelay(1000);
|
||||
}
|
||||
|
||||
clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_ENVR,
|
||||
enable ? STM32_ENVR : 0);
|
||||
if (!enable)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -14,10 +14,12 @@
|
|||
|
||||
#define ADDR_INVALID 0xFFFFFFFF
|
||||
|
||||
#define PATTERN_DEFAULT "-"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static int get_bufsize(char *string, int argc, char *argv[], int arg_nb,
|
||||
size_t *bufsize, size_t default_size)
|
||||
size_t *bufsize, size_t default_size, size_t min_size)
|
||||
{
|
||||
unsigned long value;
|
||||
|
||||
|
@ -27,13 +29,14 @@ static int get_bufsize(char *string, int argc, char *argv[], int arg_nb,
|
|||
arg_nb, argv[arg_nb]);
|
||||
return -1;
|
||||
}
|
||||
if (value > STM32_DDR_SIZE || value == 0) {
|
||||
sprintf(string, "invalid size %s", argv[arg_nb]);
|
||||
if (value > STM32_DDR_SIZE || value < min_size) {
|
||||
sprintf(string, "invalid size %s (min=%d)",
|
||||
argv[arg_nb], min_size);
|
||||
return -1;
|
||||
}
|
||||
if (value & 0x3) {
|
||||
sprintf(string, "unaligned size %s",
|
||||
argv[arg_nb]);
|
||||
if (value & (min_size - 1)) {
|
||||
sprintf(string, "unaligned size %s (min=%d)",
|
||||
argv[arg_nb], min_size);
|
||||
return -1;
|
||||
}
|
||||
*bufsize = value;
|
||||
|
@ -102,6 +105,10 @@ static int get_pattern(char *string, int argc, char *argv[], int arg_nb,
|
|||
unsigned long value;
|
||||
|
||||
if (argc > arg_nb) {
|
||||
if (!strcmp(argv[arg_nb], PATTERN_DEFAULT)) {
|
||||
*pattern = default_pattern;
|
||||
return 0;
|
||||
}
|
||||
if (strict_strtoul(argv[arg_nb], 16, &value) < 0) {
|
||||
sprintf(string, "invalid %d parameter %s",
|
||||
arg_nb, argv[arg_nb]);
|
||||
|
@ -441,7 +448,7 @@ static enum test_result test_addressbus(struct stm32mp1_ddrctl *ctl,
|
|||
u32 bufsize;
|
||||
u32 error;
|
||||
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, STM32_DDR_SIZE, 4))
|
||||
return TEST_ERROR;
|
||||
if (!is_power_of_2(bufsize)) {
|
||||
sprintf(string, "size 0x%x is not a power of 2",
|
||||
|
@ -451,6 +458,7 @@ static enum test_result test_addressbus(struct stm32mp1_ddrctl *ctl,
|
|||
if (get_addr(string, argc, argv, 1, &addr))
|
||||
return TEST_ERROR;
|
||||
|
||||
printf("running at 0x%08x length 0x%x\n", addr, bufsize);
|
||||
error = (u32)addressbus((u32 *)addr, bufsize);
|
||||
if (error) {
|
||||
sprintf(string, "0x%x: error for address 0x%x",
|
||||
|
@ -470,7 +478,7 @@ static enum test_result test_memdevice(struct stm32mp1_ddrctl *ctl,
|
|||
size_t bufsize;
|
||||
u32 error;
|
||||
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
|
||||
return TEST_ERROR;
|
||||
if (get_addr(string, argc, argv, 1, &addr))
|
||||
return TEST_ERROR;
|
||||
|
@ -512,7 +520,7 @@ static enum test_result test_sso(struct stm32mp1_ddrctl *ctl,
|
|||
u32 error = 0;
|
||||
u32 data;
|
||||
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4))
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
|
||||
return TEST_ERROR;
|
||||
if (get_addr(string, argc, argv, 1, &addr))
|
||||
return TEST_ERROR;
|
||||
|
@ -584,7 +592,7 @@ static enum test_result test_random(struct stm32mp1_ddrctl *ctl,
|
|||
u32 error = 0;
|
||||
unsigned int seed;
|
||||
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 8 * 1024))
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 8))
|
||||
return TEST_ERROR;
|
||||
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
||||
return TEST_ERROR;
|
||||
|
@ -744,7 +752,7 @@ static enum test_result test_noise_burst(struct stm32mp1_ddrctl *ctl,
|
|||
int i;
|
||||
enum test_result res = TEST_PASSED;
|
||||
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 128))
|
||||
return TEST_ERROR;
|
||||
if (get_pattern(string, argc, argv, 1, &pattern, 0xFFFFFFFF))
|
||||
return TEST_ERROR;
|
||||
|
@ -918,9 +926,11 @@ static enum test_result test_freq_pattern(struct stm32mp1_ddrctl *ctl,
|
|||
enum test_result res = TEST_PASSED, pattern_res;
|
||||
int i, bus_width;
|
||||
const u32 **patterns;
|
||||
u32 bufsize;
|
||||
u32 bufsize, addr;
|
||||
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 128))
|
||||
return TEST_ERROR;
|
||||
if (get_addr(string, argc, argv, 1, &addr))
|
||||
return TEST_ERROR;
|
||||
|
||||
switch (readl(&ctl->mstr) & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK) {
|
||||
|
@ -934,15 +944,14 @@ static enum test_result test_freq_pattern(struct stm32mp1_ddrctl *ctl,
|
|||
}
|
||||
|
||||
printf("running test pattern at 0x%08x length 0x%x width = %d\n",
|
||||
STM32_DDR_BASE, bufsize, bus_width);
|
||||
addr, bufsize, bus_width);
|
||||
|
||||
patterns =
|
||||
(const u32 **)(bus_width == 16 ? patterns_x16 : patterns_x32);
|
||||
|
||||
for (i = 0; i < NB_PATTERN; i++) {
|
||||
printf("test data pattern %s:", patterns_comments[i]);
|
||||
pattern_res = test_loop(patterns[i], (u32 *)STM32_DDR_BASE,
|
||||
bufsize);
|
||||
pattern_res = test_loop(patterns[i], (u32 *)addr, bufsize);
|
||||
if (pattern_res != TEST_PASSED) {
|
||||
printf("Failed\n");
|
||||
return pattern_res;
|
||||
|
@ -1007,7 +1016,7 @@ static enum test_result test_checkboard(struct stm32mp1_ddrctl *ctl,
|
|||
|
||||
u32 checkboard[2] = {0x55555555, 0xAAAAAAAA};
|
||||
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 8))
|
||||
return TEST_ERROR;
|
||||
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
||||
return TEST_ERROR;
|
||||
|
@ -1042,7 +1051,7 @@ static enum test_result test_blockseq(struct stm32mp1_ddrctl *ctl,
|
|||
u32 bufsize, nb_loop, loop = 0, addr, value;
|
||||
int i;
|
||||
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
|
||||
return TEST_ERROR;
|
||||
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
||||
return TEST_ERROR;
|
||||
|
@ -1076,7 +1085,7 @@ static enum test_result test_walkbit0(struct stm32mp1_ddrctl *ctl,
|
|||
u32 bufsize, nb_loop, loop = 0, addr, value;
|
||||
int i;
|
||||
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
|
||||
return TEST_ERROR;
|
||||
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
||||
return TEST_ERROR;
|
||||
|
@ -1114,7 +1123,7 @@ static enum test_result test_walkbit1(struct stm32mp1_ddrctl *ctl,
|
|||
u32 bufsize, nb_loop, loop = 0, addr, value;
|
||||
int i;
|
||||
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
|
||||
return TEST_ERROR;
|
||||
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
||||
return TEST_ERROR;
|
||||
|
@ -1156,7 +1165,7 @@ static enum test_result test_bitspread(struct stm32mp1_ddrctl *ctl,
|
|||
u32 bufsize, nb_loop, loop = 0, addr, bitspread[4];
|
||||
int i, j;
|
||||
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 32))
|
||||
return TEST_ERROR;
|
||||
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
||||
return TEST_ERROR;
|
||||
|
@ -1203,7 +1212,7 @@ static enum test_result test_bitflip(struct stm32mp1_ddrctl *ctl,
|
|||
|
||||
u32 bitflip[4];
|
||||
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
||||
if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 32))
|
||||
return TEST_ERROR;
|
||||
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
||||
return TEST_ERROR;
|
||||
|
@ -1340,17 +1349,52 @@ static enum test_result test_all(struct stm32mp1_ddrctl *ctl,
|
|||
char *string, int argc, char *argv[])
|
||||
{
|
||||
enum test_result res = TEST_PASSED, result;
|
||||
int i, nb_error = 0;
|
||||
int i, j, nb_error = 0, len;
|
||||
u32 loop = 0, nb_loop;
|
||||
int argc_test;
|
||||
char *argv_test[4];
|
||||
char loop_string[] = "1";
|
||||
char pattern_string[] = PATTERN_DEFAULT;
|
||||
u32 *addr;
|
||||
|
||||
if (get_nb_loop(string, argc, argv, 0, &nb_loop, 1))
|
||||
return TEST_ERROR;
|
||||
|
||||
if (get_addr(string, argc, argv, 2, (u32 *)&addr))
|
||||
return TEST_ERROR;
|
||||
|
||||
while (!nb_error) {
|
||||
/* execute all the test except the lasts which are infinite */
|
||||
for (i = 1; i < test_nb - NB_TEST_INFINITE; i++) {
|
||||
argc_test = 0;
|
||||
j = 0;
|
||||
len = strlen(test[i].usage);
|
||||
if (argc > 1 && j < len &&
|
||||
!strncmp("[size]", &test[i].usage[j], 6)) {
|
||||
argv_test[argc_test++] = argv[1];
|
||||
j += 7;
|
||||
}
|
||||
if (argc > 2) {
|
||||
if (j < len &&
|
||||
!strncmp("[loop]", &test[i].usage[j], 6)) {
|
||||
argv_test[argc_test++] = loop_string;
|
||||
j += 7;
|
||||
}
|
||||
if (j < len &&
|
||||
!strncmp("[pattern]", &test[i].usage[j],
|
||||
9)) {
|
||||
argv_test[argc_test++] = pattern_string;
|
||||
j += 10;
|
||||
}
|
||||
if (j < len &&
|
||||
!strncmp("[addr]", &test[i].usage[j], 6)) {
|
||||
argv_test[argc_test++] = argv[2];
|
||||
j += 7;
|
||||
}
|
||||
}
|
||||
printf("execute %d:%s\n", (int)i, test[i].name);
|
||||
result = test[i].fct(ctl, phy, string, 0, NULL);
|
||||
result = test[i].fct(ctl, phy, string,
|
||||
argc_test, argv_test);
|
||||
printf("result %d:%s = ", (int)i, test[i].name);
|
||||
if (result != TEST_PASSED) {
|
||||
nb_error++;
|
||||
|
@ -1381,7 +1425,7 @@ static enum test_result test_all(struct stm32mp1_ddrctl *ctl,
|
|||
****************************************************************/
|
||||
|
||||
const struct test_desc test[] = {
|
||||
{test_all, "All", "[loop]", "Execute all tests", 1 },
|
||||
{test_all, "All", "[loop] [size] [addr]", "Execute all tests", 3 },
|
||||
{test_databus, "Simple DataBus", "[addr]",
|
||||
"Verifies each data line by walking 1 on fixed address",
|
||||
1
|
||||
|
@ -1418,9 +1462,9 @@ const struct test_desc test[] = {
|
|||
"Verifies r/w and memcopy(burst for pseudo random value.",
|
||||
3
|
||||
},
|
||||
{test_freq_pattern, "FrequencySelectivePattern", "[size]",
|
||||
{test_freq_pattern, "FrequencySelectivePattern", "[size] [addr]",
|
||||
"write & test patterns: Mostly Zero, Mostly One and F/n",
|
||||
1
|
||||
2
|
||||
},
|
||||
{test_blockseq, "BlockSequential", "[size] [loop] [addr]",
|
||||
"test incremental pattern",
|
||||
|
|
|
@ -123,7 +123,7 @@
|
|||
* for serial/usb: execute the stm32prog command
|
||||
* for mmc boot (eMMC, SD card), boot only on the same device
|
||||
* for nand or spi-nand boot, boot with on ubifs partition on UBI partition
|
||||
* for nor boot, use the default order
|
||||
* for nor boot, use SD card = mmc0
|
||||
*/
|
||||
#define STM32MP_BOOTCMD "bootcmd_stm32mp=" \
|
||||
"echo \"Boot over ${boot_device}${boot_instance}!\";" \
|
||||
|
@ -136,6 +136,8 @@
|
|||
"if test ${boot_device} = nand ||" \
|
||||
" test ${boot_device} = spi-nand ;" \
|
||||
"then env set boot_targets ubifs0; fi;" \
|
||||
"if test ${boot_device} = nor;" \
|
||||
"then env set boot_targets mmc0; fi;" \
|
||||
"run distro_bootcmd;" \
|
||||
"fi;\0"
|
||||
|
||||
|
@ -155,9 +157,7 @@
|
|||
"splashimage=0xc4300000\0" \
|
||||
"ramdisk_addr_r=0xc4400000\0" \
|
||||
"altbootcmd=run bootcmd\0" \
|
||||
"env_default=1\0" \
|
||||
"env_check=if test $env_default -eq 1;"\
|
||||
" then env set env_default 0;env save;fi\0" \
|
||||
"env_check=if env info -p -d; then env save; fi\0" \
|
||||
STM32MP_BOOTCMD \
|
||||
BOOTENV \
|
||||
"boot_net_usb_start=true\0"
|
||||
|
|
Loading…
Reference in a new issue