- 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:
Tom Rini 2020-07-07 14:00:44 -04:00
commit 1e88e78177
39 changed files with 1165 additions and 459 deletions

View file

@ -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;
};

View file

@ -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>;
};

View file

@ -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";

View file

@ -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";

View file

@ -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>;

View file

@ -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";

View file

@ -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";

View file

@ -116,6 +116,14 @@
status = "okay";
};
&cpu0{
cpu-supply = <&vddcore>;
};
&cpu1{
cpu-supply = <&vddcore>;
};
&ethernet0 {
status = "okay";
pinctrl-0 = <&ethernet0_rgmii_pins_a>;

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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) {

View file

@ -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)

View 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);

View file

@ -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);

View file

@ -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

View file

@ -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();

View file

@ -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.

View file

@ -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
View 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);
}
}

View 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);

View 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,
};

View 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

View file

@ -8,5 +8,3 @@ obj-y += spl.o
else
obj-y += stm32mp1.o
endif
obj-y += board.o

View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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(&regs->moder, mask, mode << bits_index);
}
static int stm32_gpio_get_moder(struct stm32_gpio_regs *regs, int idx)
{
return (readl(&regs->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(&regs->otyper, OTYPE_MSK << bits, otype << bits);
}
static enum stm32_gpio_otype stm32_gpio_get_otype(struct stm32_gpio_regs *regs,
int idx)
{
return (readl(&regs->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(&regs->pupdr, PUPD_MASK << bits, pupd << bits);
}
static enum stm32_gpio_pupd stm32_gpio_get_pupd(struct stm32_gpio_regs *regs,
int idx)
{
return (readl(&regs->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(&regs->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(&regs->moder, mask, STM32_GPIO_MODE_OUT << bits_index);
stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT);
writel(BSRR_BIT(idx, value), &regs->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), &regs->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(&regs->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)

View file

@ -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
},
{

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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",

View file

@ -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"