Add driver to manage onboard hub supplies

Add calibration support for stm32-adc
 Linux kernel v6.1 DT synchronization for stm32mp151.dtsi
 stm32mp157a-dk1-scmi-u-boot.dtsi update
 Add support of OP-TEE and STM32MP13x in bsec driver
 ECDSA various fixes for stm32mp
 -----BEGIN PGP SIGNATURE-----
 
 iQJQBAABCgA6FiEEXyrViUccKBz9c35Jysd4L3sz/6YFAmPBXKccHHBhdHJpY2Uu
 Y2hvdGFyZEBmb3NzLnN0LmNvbQAKCRDKx3gvezP/pqAsD/9DhQqYRxCNdFmvchPq
 svu9qB/9lig27IjjLdnUQpIp2xbMH7ki90JrV9Bk6uet6+46mtNlddLhUjJmlEG3
 QQGJzEohYQO7T2RZ1PoHbgQMow/wkZn0Li0zDYW2FHlBdZP1Yd4c+rjiVyYg0oHZ
 z5B/QkXIIo5czVRixwU7RzERfHWbzRAVSJ9nqnchOZCt25gkTwfzoeOtdjg3/H48
 AmdMs4/z3Vcc4MkMAb3rQbPGCjrlzPEVSEPiGQrSNoVl7u6sRz24gJ0uoJV9NRY+
 8IsAHXMZ4agYUnBSilupTZDOwg9RzX1NammY7a9Fw5Ew0qI7YoolhsEoChBeBXGM
 IfH8MB5Jiw1aZpUL6bHX83OpVgpDl/yIZyfWniXQq7tDgwNq6NEtigyDnFr8Z4bS
 QuLmSCDprRM3OuhZTb6ZQBg4A4mRGU4ASOaVyb0kQ+x6zEVeklxi1EAYIVggKWem
 DimaSa2zqjWieYQy5JmhraH7Qnb4/OfgtXl9Yj3s1P1bI7kuuCSzJOeBl8Gv13pK
 kJQG73ar4CEg3hxTXtrrQ6Vl9ti0K2GGaeq2IZP7MJDSIKitgZIIc+b0jku0pfr8
 ep6Ecql1xVExYPqn4Y9pVT6YuuRy2M+ag3dbtBWv79h0oSZUuDFy8RZssHXYA/RB
 zzGwJT0N9U2Zm0VxTCz2wBioLQ==
 =SNID
 -----END PGP SIGNATURE-----

Merge tag 'u-boot-stm32-20230113' of https://source.denx.de/u-boot/custodians/u-boot-stm

Add driver to manage onboard hub supplies
Add calibration support for stm32-adc
Linux kernel v6.1 DT synchronization for stm32mp151.dtsi
stm32mp157a-dk1-scmi-u-boot.dtsi update
Add support of OP-TEE and STM32MP13x in bsec driver
ECDSA various fixes for stm32mp
This commit is contained in:
Tom Rini 2023-01-13 09:56:19 -05:00
commit fe4c21de4f
25 changed files with 514 additions and 93 deletions

View File

@ -145,6 +145,8 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x40000000 0x400>; reg = <0x40000000 0x400>;
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc TIM2_K>; clocks = <&rcc TIM2_K>;
clock-names = "int"; clock-names = "int";
dmas = <&dmamux1 18 0x400 0x1>, dmas = <&dmamux1 18 0x400 0x1>,
@ -178,6 +180,8 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x40001000 0x400>; reg = <0x40001000 0x400>;
interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc TIM3_K>; clocks = <&rcc TIM3_K>;
clock-names = "int"; clock-names = "int";
dmas = <&dmamux1 23 0x400 0x1>, dmas = <&dmamux1 23 0x400 0x1>,
@ -212,6 +216,8 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x40002000 0x400>; reg = <0x40002000 0x400>;
interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc TIM4_K>; clocks = <&rcc TIM4_K>;
clock-names = "int"; clock-names = "int";
dmas = <&dmamux1 29 0x400 0x1>, dmas = <&dmamux1 29 0x400 0x1>,
@ -244,6 +250,8 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x40003000 0x400>; reg = <0x40003000 0x400>;
interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc TIM5_K>; clocks = <&rcc TIM5_K>;
clock-names = "int"; clock-names = "int";
dmas = <&dmamux1 55 0x400 0x1>, dmas = <&dmamux1 55 0x400 0x1>,
@ -278,6 +286,8 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x40004000 0x400>; reg = <0x40004000 0x400>;
interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc TIM6_K>; clocks = <&rcc TIM6_K>;
clock-names = "int"; clock-names = "int";
dmas = <&dmamux1 69 0x400 0x1>; dmas = <&dmamux1 69 0x400 0x1>;
@ -296,6 +306,8 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x40005000 0x400>; reg = <0x40005000 0x400>;
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc TIM7_K>; clocks = <&rcc TIM7_K>;
clock-names = "int"; clock-names = "int";
dmas = <&dmamux1 70 0x400 0x1>; dmas = <&dmamux1 70 0x400 0x1>;
@ -314,6 +326,8 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x40006000 0x400>; reg = <0x40006000 0x400>;
interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc TIM12_K>; clocks = <&rcc TIM12_K>;
clock-names = "int"; clock-names = "int";
status = "disabled"; status = "disabled";
@ -336,6 +350,8 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x40007000 0x400>; reg = <0x40007000 0x400>;
interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc TIM13_K>; clocks = <&rcc TIM13_K>;
clock-names = "int"; clock-names = "int";
status = "disabled"; status = "disabled";
@ -358,6 +374,8 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x40008000 0x400>; reg = <0x40008000 0x400>;
interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc TIM14_K>; clocks = <&rcc TIM14_K>;
clock-names = "int"; clock-names = "int";
status = "disabled"; status = "disabled";
@ -641,6 +659,11 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x44000000 0x400>; reg = <0x44000000 0x400>;
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "brk", "up", "trg-com", "cc";
clocks = <&rcc TIM1_K>; clocks = <&rcc TIM1_K>;
clock-names = "int"; clock-names = "int";
dmas = <&dmamux1 11 0x400 0x1>, dmas = <&dmamux1 11 0x400 0x1>,
@ -677,6 +700,11 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x44001000 0x400>; reg = <0x44001000 0x400>;
interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "brk", "up", "trg-com", "cc";
clocks = <&rcc TIM8_K>; clocks = <&rcc TIM8_K>;
clock-names = "int"; clock-names = "int";
dmas = <&dmamux1 47 0x400 0x1>, dmas = <&dmamux1 47 0x400 0x1>,
@ -764,6 +792,8 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x44006000 0x400>; reg = <0x44006000 0x400>;
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc TIM15_K>; clocks = <&rcc TIM15_K>;
clock-names = "int"; clock-names = "int";
dmas = <&dmamux1 105 0x400 0x1>, dmas = <&dmamux1 105 0x400 0x1>,
@ -791,6 +821,8 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x44007000 0x400>; reg = <0x44007000 0x400>;
interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc TIM16_K>; clocks = <&rcc TIM16_K>;
clock-names = "int"; clock-names = "int";
dmas = <&dmamux1 109 0x400 0x1>, dmas = <&dmamux1 109 0x400 0x1>,
@ -815,6 +847,8 @@
#size-cells = <0>; #size-cells = <0>;
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x44008000 0x400>; reg = <0x44008000 0x400>;
interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc TIM17_K>; clocks = <&rcc TIM17_K>;
clock-names = "int"; clock-names = "int";
dmas = <&dmamux1 111 0x400 0x1>, dmas = <&dmamux1 111 0x400 0x1>,

View File

@ -3,7 +3,6 @@
* Copyright : STMicroelectronics 2022 * Copyright : STMicroelectronics 2022
*/ */
#include <dt-bindings/clock/stm32mp1-clksrc.h>
#include "stm32mp15-scmi-u-boot.dtsi" #include "stm32mp15-scmi-u-boot.dtsi"
/ { / {

View File

@ -3,7 +3,6 @@
* Copyright : STMicroelectronics 2022 * Copyright : STMicroelectronics 2022
*/ */
#include <dt-bindings/clock/stm32mp1-clksrc.h>
#include "stm32mp15-scmi-u-boot.dtsi" #include "stm32mp15-scmi-u-boot.dtsi"
/ { / {

View File

@ -362,6 +362,14 @@
&usbh_ehci { &usbh_ehci {
phys = <&usbphyc_port0>; phys = <&usbphyc_port0>;
status = "okay"; status = "okay";
#address-cells = <1>;
#size-cells = <0>;
/* onboard HUB */
hub@1 {
compatible = "usb424,2514";
reg = <1>;
vdd-supply = <&v3v3>;
};
}; };
&usbotg_hs { &usbotg_hs {
@ -385,6 +393,10 @@
st,tune-squelch-level = <3>; st,tune-squelch-level = <3>;
st,tune-hs-rx-offset = <2>; st,tune-hs-rx-offset = <2>;
st,no-lsfs-sc; st,no-lsfs-sc;
connector {
compatible = "usb-a-connector";
vbus-supply = <&vbus_sw>;
};
}; };
&usbphyc_port1 { &usbphyc_port1 {

View File

@ -390,21 +390,21 @@
regulator-always-on; regulator-always-on;
}; };
bst_out: boost { bst_out: boost {
regulator-name = "bst_out"; regulator-name = "bst_out";
interrupts = <IT_OCP_BOOST 0>; interrupts = <IT_OCP_BOOST 0>;
}; };
vbus_otg: pwr_sw1 { vbus_otg: pwr_sw1 {
regulator-name = "vbus_otg"; regulator-name = "vbus_otg";
interrupts = <IT_OCP_OTG 0>; interrupts = <IT_OCP_OTG 0>;
}; };
vbus_sw: pwr_sw2 { vbus_sw: pwr_sw2 {
regulator-name = "vbus_sw"; regulator-name = "vbus_sw";
interrupts = <IT_OCP_SWOUT 0>; interrupts = <IT_OCP_SWOUT 0>;
regulator-active-discharge = <1>; regulator-active-discharge = <1>;
}; };
}; };
onkey { onkey {

View File

@ -11,10 +11,10 @@ obj-y += bsec.o
obj-$(CONFIG_STM32MP13x) += stm32mp13x.o obj-$(CONFIG_STM32MP13x) += stm32mp13x.o
obj-$(CONFIG_STM32MP15x) += stm32mp15x.o obj-$(CONFIG_STM32MP15x) += stm32mp15x.o
obj-$(CONFIG_STM32_ECDSA_VERIFY) += ecdsa_romapi.o
ifdef CONFIG_SPL_BUILD ifdef CONFIG_SPL_BUILD
obj-y += spl.o obj-y += spl.o
obj-y += tzc400.o obj-y += tzc400.o
obj-$(CONFIG_STM32_ECDSA_VERIFY) += ecdsa_romapi.o
else else
obj-y += cmd_stm32prog/ obj-y += cmd_stm32prog/
obj-$(CONFIG_CMD_STM32KEY) += cmd_stm32key.o obj-$(CONFIG_CMD_STM32KEY) += cmd_stm32key.o

View File

@ -8,33 +8,18 @@
#include <common.h> #include <common.h>
#include <log.h> #include <log.h>
#include <linux/libfdt.h> #include <linux/libfdt.h>
#include <asm/arch/sys_proto.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/system.h> #include <asm/system.h>
/*
* Force data-section, as .bss will not be valid
* when save_boot_params is invoked.
*/
static unsigned long nt_fw_dtb __section(".data");
/*
* Save the FDT address provided by TF-A in r2 at boot time
* This function is called from start.S
*/
void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2,
unsigned long r3)
{
nt_fw_dtb = r2;
save_boot_params_ret();
}
/* /*
* Use the saved FDT address provided by TF-A at boot time (NT_FW_CONFIG = * Use the saved FDT address provided by TF-A at boot time (NT_FW_CONFIG =
* Non Trusted Firmware configuration file) when the pointer is valid * Non Trusted Firmware configuration file) when the pointer is valid
*/ */
void *board_fdt_blob_setup(int *err) void *board_fdt_blob_setup(int *err)
{ {
unsigned long nt_fw_dtb = get_stm32mp_bl2_dtb();
log_debug("%s: nt_fw_dtb=%lx\n", __func__, nt_fw_dtb); log_debug("%s: nt_fw_dtb=%lx\n", __func__, nt_fw_dtb);
*err = 0; *err = 0;

View File

@ -10,9 +10,11 @@
#include <dm.h> #include <dm.h>
#include <log.h> #include <log.h>
#include <misc.h> #include <misc.h>
#include <tee.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/arch/bsec.h> #include <asm/arch/bsec.h>
#include <asm/arch/stm32mp1_smc.h> #include <asm/arch/stm32mp1_smc.h>
#include <dm/device.h>
#include <dm/device_compat.h> #include <dm/device_compat.h>
#include <linux/arm-smccc.h> #include <linux/arm-smccc.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
@ -63,10 +65,43 @@
*/ */
#define BSEC_LOCK_PROGRAM 0x04 #define BSEC_LOCK_PROGRAM 0x04
#define PTA_BSEC_UUID { 0x94cf71ad, 0x80e6, 0x40b5, \
{ 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03 } }
/* /*
* OTP status: bit 0 permanent lock * Read OTP memory
*
* [in] value[0].a OTP start offset in byte
* [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
* [out] memref[1].buffer Output buffer to store read values
* [out] memref[1].size Size of OTP to be read
*
* Return codes:
* TEE_SUCCESS - Invoke command success
* TEE_ERROR_BAD_PARAMETERS - Incorrect input param
* TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
*/ */
#define BSEC_LOCK_PERM BIT(0) #define PTA_BSEC_READ_MEM 0x0
/*
* Write OTP memory
*
* [in] value[0].a OTP start offset in byte
* [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
* [in] memref[1].buffer Input buffer to read values
* [in] memref[1].size Size of OTP to be written
*
* Return codes:
* TEE_SUCCESS - Invoke command success
* TEE_ERROR_BAD_PARAMETERS - Incorrect input param
* TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
*/
#define PTA_BSEC_WRITE_MEM 0x1
/* value of PTA_BSEC access type = value[in] b */
#define SHADOW_ACCESS 0
#define FUSE_ACCESS 1
#define LOCK_ACCESS 2
/** /**
* bsec_lock() - manage lock for each type SR/SP/SW * bsec_lock() - manage lock for each type SR/SP/SW
@ -359,6 +394,10 @@ struct stm32mp_bsec_plat {
u32 base; u32 base;
}; };
struct stm32mp_bsec_priv {
struct udevice *tee;
};
static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp) static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
{ {
struct stm32mp_bsec_plat *plat; struct stm32mp_bsec_plat *plat;
@ -468,18 +507,111 @@ static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
plat = dev_get_plat(dev); plat = dev_get_plat(dev);
return bsec_permanent_lock_otp(dev, plat->base, otp); return bsec_permanent_lock_otp(dev, plat->base, otp);
}
return -EINVAL; static int bsec_pta_open_session(struct udevice *tee, u32 *tee_session)
{
const struct tee_optee_ta_uuid uuid = PTA_BSEC_UUID;
struct tee_open_session_arg arg;
int rc;
memset(&arg, 0, sizeof(arg));
tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
arg.clnt_login = TEE_LOGIN_REE_KERNEL;
rc = tee_open_session(tee, &arg, 0, NULL);
if (rc < 0)
return -ENODEV;
*tee_session = arg.session;
return 0;
}
static int bsec_optee_open(struct udevice *dev)
{
struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
struct udevice *tee;
u32 tee_session;
int rc;
tee = tee_find_device(NULL, NULL, NULL, NULL);
if (!tee)
return -ENODEV;
/* try to open the STM32 BSEC TA */
rc = bsec_pta_open_session(tee, &tee_session);
if (rc)
return rc;
tee_close_session(tee, tee_session);
priv->tee = tee;
return 0;
}
static int bsec_optee_pta(struct udevice *dev, int cmd, int type, int offset,
void *buff, ulong size)
{
struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
u32 tee_session;
struct tee_invoke_arg arg;
struct tee_param param[2];
struct tee_shm *fw_shm;
int rc;
rc = bsec_pta_open_session(priv->tee, &tee_session);
if (rc)
return rc;
rc = tee_shm_register(priv->tee, buff, size, 0, &fw_shm);
if (rc)
goto close_session;
memset(&arg, 0, sizeof(arg));
arg.func = cmd;
arg.session = tee_session;
memset(param, 0, sizeof(param));
param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
param[0].u.value.a = offset;
param[0].u.value.b = type;
if (cmd == PTA_BSEC_WRITE_MEM)
param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
else
param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
param[1].u.memref.shm = fw_shm;
param[1].u.memref.size = size;
rc = tee_invoke_func(priv->tee, &arg, 2, param);
if (rc < 0 || arg.ret != 0) {
dev_err(priv->tee,
"PTA_BSEC invoke failed TEE err: %x, err:%x\n",
arg.ret, rc);
if (!rc)
rc = -EIO;
}
tee_shm_free(fw_shm);
close_session:
tee_close_session(priv->tee, tee_session);
return rc;
} }
static int stm32mp_bsec_read(struct udevice *dev, int offset, static int stm32mp_bsec_read(struct udevice *dev, int offset,
void *buf, int size) void *buf, int size)
{ {
struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
int ret; int ret;
int i; int i;
bool shadow = true, lock = false; bool shadow = true, lock = false;
int nb_otp = size / sizeof(u32); int nb_otp = size / sizeof(u32);
int otp; int otp, cmd;
unsigned int offs = offset; unsigned int offs = offset;
if (offs >= STM32_BSEC_LOCK_OFFSET) { if (offs >= STM32_BSEC_LOCK_OFFSET) {
@ -493,6 +625,19 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset,
if ((offs % 4) || (size % 4)) if ((offs % 4) || (size % 4))
return -EINVAL; return -EINVAL;
if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
cmd = FUSE_ACCESS;
if (shadow)
cmd = SHADOW_ACCESS;
if (lock)
cmd = LOCK_ACCESS;
ret = bsec_optee_pta(dev, PTA_BSEC_READ_MEM, cmd, offs, buf, size);
if (ret)
return ret;
return size;
}
otp = offs / sizeof(u32); otp = offs / sizeof(u32);
for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) { for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) {
@ -517,11 +662,12 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset,
static int stm32mp_bsec_write(struct udevice *dev, int offset, static int stm32mp_bsec_write(struct udevice *dev, int offset,
const void *buf, int size) const void *buf, int size)
{ {
struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
int ret = 0; int ret = 0;
int i; int i;
bool shadow = true, lock = false; bool shadow = true, lock = false;
int nb_otp = size / sizeof(u32); int nb_otp = size / sizeof(u32);
int otp; int otp, cmd;
unsigned int offs = offset; unsigned int offs = offset;
if (offs >= STM32_BSEC_LOCK_OFFSET) { if (offs >= STM32_BSEC_LOCK_OFFSET) {
@ -535,6 +681,19 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset,
if ((offs % 4) || (size % 4)) if ((offs % 4) || (size % 4))
return -EINVAL; return -EINVAL;
if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
cmd = FUSE_ACCESS;
if (shadow)
cmd = SHADOW_ACCESS;
if (lock)
cmd = LOCK_ACCESS;
ret = bsec_optee_pta(dev, PTA_BSEC_WRITE_MEM, cmd, offs, (void *)buf, size);
if (ret)
return ret;
return size;
}
otp = offs / sizeof(u32); otp = offs / sizeof(u32);
for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) { for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) {
@ -583,6 +742,9 @@ static int stm32mp_bsec_probe(struct udevice *dev)
return ret; return ret;
} }
if (IS_ENABLED(CONFIG_OPTEE))
bsec_optee_open(dev);
/* /*
* update unlocked shadow for OTP cleared by the rom code * update unlocked shadow for OTP cleared by the rom code
* only executed in SPL, it is done in TF-A for TFABOOT * only executed in SPL, it is done in TF-A for TFABOOT
@ -599,6 +761,7 @@ static int stm32mp_bsec_probe(struct udevice *dev)
} }
static const struct udevice_id stm32mp_bsec_ids[] = { static const struct udevice_id stm32mp_bsec_ids[] = {
{ .compatible = "st,stm32mp13-bsec" },
{ .compatible = "st,stm32mp15-bsec" }, { .compatible = "st,stm32mp15-bsec" },
{} {}
}; };
@ -608,7 +771,8 @@ U_BOOT_DRIVER(stm32mp_bsec) = {
.id = UCLASS_MISC, .id = UCLASS_MISC,
.of_match = stm32mp_bsec_ids, .of_match = stm32mp_bsec_ids,
.of_to_plat = stm32mp_bsec_of_to_plat, .of_to_plat = stm32mp_bsec_of_to_plat,
.plat_auto = sizeof(struct stm32mp_bsec_plat), .plat_auto = sizeof(struct stm32mp_bsec_plat),
.priv_auto = sizeof(struct stm32mp_bsec_priv),
.ops = &stm32mp_bsec_ops, .ops = &stm32mp_bsec_ops,
.probe = stm32mp_bsec_probe, .probe = stm32mp_bsec_probe,
}; };

View File

@ -8,6 +8,7 @@
#include <console.h> #include <console.h>
#include <log.h> #include <log.h>
#include <misc.h> #include <misc.h>
#include <asm/arch/bsec.h>
#include <dm/device.h> #include <dm/device.h>
#include <dm/uclass.h> #include <dm/uclass.h>
@ -84,9 +85,6 @@ static u32 get_otp_close_mask(void)
return STM32_OTP_STM32MP15x_CLOSE_MASK; return STM32_OTP_STM32MP15x_CLOSE_MASK;
} }
#define BSEC_LOCK_ERROR (-1)
#define BSEC_LOCK_PERM BIT(0)
static int get_misc_dev(struct udevice **dev) static int get_misc_dev(struct udevice **dev)
{ {
int ret; int ret;

View File

@ -22,6 +22,7 @@
#include <dm/device.h> #include <dm/device.h>
#include <dm/uclass.h> #include <dm/uclass.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <spl.h>
/* /*
* early TLB into the .data section so that it not get cleared * early TLB into the .data section so that it not get cleared
@ -378,3 +379,52 @@ int arch_misc_init(void)
return 0; return 0;
} }
/*
* Without forcing the ".data" section, this would get saved in ".bss". BSS
* will be cleared soon after, so it's not suitable.
*/
static uintptr_t rom_api_table __section(".data");
static uintptr_t nt_fw_dtb __section(".data");
/*
* The ROM gives us the API location in r0 when starting. This is only available
* during SPL, as there isn't (yet) a mechanism to pass this on to u-boot. Save
* the FDT address provided by TF-A in r2 at boot time. This function is called
* from start.S
*/
void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2,
unsigned long r3)
{
if (IS_ENABLED(CONFIG_STM32_ECDSA_VERIFY))
rom_api_table = r0;
if (IS_ENABLED(CONFIG_TFABOOT))
nt_fw_dtb = r2;
save_boot_params_ret();
}
uintptr_t get_stm32mp_rom_api_table(void)
{
return rom_api_table;
}
uintptr_t get_stm32mp_bl2_dtb(void)
{
return nt_fw_dtb;
}
#ifdef CONFIG_SPL_BUILD
void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
{
typedef void __noreturn (*image_entry_stm32_t)(u32 romapi);
uintptr_t romapi = get_stm32mp_rom_api_table();
image_entry_stm32_t image_entry =
(image_entry_stm32_t)spl_image->entry_point;
printf("image entry point: 0x%lx\n", spl_image->entry_point);
image_entry(romapi);
}
#endif

View File

@ -24,26 +24,10 @@ struct ecdsa_rom_api {
uint32_t ecc_algo); uint32_t ecc_algo);
}; };
/*
* Without forcing the ".data" section, this would get saved in ".bss". BSS
* will be cleared soon after, so it's not suitable.
*/
static uintptr_t rom_api_loc __section(".data");
/*
* The ROM gives us the API location in r0 when starting. This is only available
* during SPL, as there isn't (yet) a mechanism to pass this on to u-boot.
*/
void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2,
unsigned long r3)
{
rom_api_loc = r0;
save_boot_params_ret();
}
static void stm32mp_rom_get_ecdsa_functions(struct ecdsa_rom_api *rom) static void stm32mp_rom_get_ecdsa_functions(struct ecdsa_rom_api *rom)
{ {
uintptr_t verify_ptr = rom_api_loc + ROM_API_OFFSET_ECDSA_VERIFY; uintptr_t verify_ptr = get_stm32mp_rom_api_table() +
ROM_API_OFFSET_ECDSA_VERIFY;
rom->ecdsa_verify_signature = *(void **)verify_ptr; rom->ecdsa_verify_signature = *(void **)verify_ptr;
} }
@ -81,6 +65,10 @@ static int romapi_ecdsa_verify(struct udevice *dev,
memcpy(raw_key + 32, pubkey->y, 32); memcpy(raw_key + 32, pubkey->y, 32);
stm32mp_rom_get_ecdsa_functions(&rom); stm32mp_rom_get_ecdsa_functions(&rom);
/* Mark BootROM region as executable. */
mmu_set_region_dcache_behaviour(0, SZ_2M, DCACHE_DEFAULT_OPTION);
rom_ret = rom.ecdsa_verify_signature(hash, raw_key, signature, algo); rom_ret = rom.ecdsa_verify_signature(hash, raw_key, signature, algo);
return rom_ret == ROM_API_SUCCESS ? 0 : -EPERM; return rom_ret == ROM_API_SUCCESS ? 0 : -EPERM;

View File

@ -5,3 +5,10 @@
/* check self hosted debug status = BSEC_DENABLE.DBGSWENABLE */ /* check self hosted debug status = BSEC_DENABLE.DBGSWENABLE */
bool bsec_dbgswenable(void); bool bsec_dbgswenable(void);
/* Bitfield definition for LOCK status */
#define BSEC_LOCK_PERM BIT(30)
#define BSEC_LOCK_SHADOW_R BIT(29)
#define BSEC_LOCK_SHADOW_W BIT(28)
#define BSEC_LOCK_SHADOW_P BIT(27)
#define BSEC_LOCK_ERROR BIT(26)

View File

@ -77,3 +77,6 @@ void stm32mp_misc_init(void);
/* helper function: read data from OTP */ /* helper function: read data from OTP */
u32 get_otp(int index, int shift, int mask); u32 get_otp(int index, int shift, int mask);
uintptr_t get_stm32mp_rom_api_table(void);
uintptr_t get_stm32mp_bl2_dtb(void);

View File

@ -1,7 +1,7 @@
config CMD_STBOARD config CMD_STBOARD
bool "stboard - command for OTP board information" bool "stboard - command for OTP board information"
depends on ARCH_STM32MP depends on ARCH_STM32MP
default y if TARGET_ST_STM32MP15x default y if TARGET_ST_STM32MP15x || TARGET_ST_STM32MP13x
help help
This compile the stboard command to This compile the stboard command to
read and write the board in the OTP. read and write the board in the OTP.

View File

@ -2,8 +2,8 @@
/* /*
* Copyright (C) 2019, STMicroelectronics - All Rights Reserved * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
* *
* the st command stboard supports the STMicroelectronics board identification * the command stboard supports the STMicroelectronics board identification
* saved in OTP 59. * saved in OTP_BOARD.
* *
* The ST product codification have several element * The ST product codification have several element
* - "Commercial Product Name" (CPN): type of product board (DKX, EVX) * - "Commercial Product Name" (CPN): type of product board (DKX, EVX)
@ -18,7 +18,7 @@
* - Finished Good = EVA32MP157A1$AU1 * - Finished Good = EVA32MP157A1$AU1
* *
* Both information are written on board and these information are also saved * Both information are written on board and these information are also saved
* in OTP59, with: * in OTP_BOARD (59 for STM32MP15x or 60 for STM32MP13x), with:
* bit [31:16] (hex) => Board id, MBxxxx * bit [31:16] (hex) => Board id, MBxxxx
* bit [15:12] (dec) => Variant CPN (1....15) * bit [15:12] (dec) => Variant CPN (1....15)
* bit [11:8] (dec) => Revision board (index with A = 1, Z = 26) * bit [11:8] (dec) => Revision board (index with A = 1, Z = 26)
@ -34,6 +34,7 @@
#include <command.h> #include <command.h>
#include <console.h> #include <console.h>
#include <misc.h> #include <misc.h>
#include <asm/arch/bsec.h>
#include <dm/device.h> #include <dm/device.h>
#include <dm/uclass.h> #include <dm/uclass.h>
@ -48,6 +49,7 @@ static bool check_stboard(u16 board)
0x1298, 0x1298,
0x1341, 0x1341,
0x1497, 0x1497,
0x1635,
}; };
for (i = 0; i < ARRAY_SIZE(st_board_id); i++) for (i = 0; i < ARRAY_SIZE(st_board_id); i++)
@ -109,7 +111,7 @@ static int do_stboard(struct cmd_tbl *cmdtp, int flag, int argc,
else else
display_stboard(otp); display_stboard(otp);
printf(" OTP %d %s locked !\n", BSEC_OTP_BOARD, printf(" OTP %d %s locked !\n", BSEC_OTP_BOARD,
lock == 1 ? "" : "NOT"); lock & BSEC_LOCK_PERM ? "" : "NOT");
return CMD_RET_SUCCESS; return CMD_RET_SUCCESS;
} }
@ -178,7 +180,7 @@ static int do_stboard(struct cmd_tbl *cmdtp, int flag, int argc,
} }
/* write persistent lock */ /* write persistent lock */
otp = 1; otp = BSEC_LOCK_PERM;
ret = misc_write(dev, STM32_BSEC_LOCK(BSEC_OTP_BOARD), ret = misc_write(dev, STM32_BSEC_LOCK(BSEC_OTP_BOARD),
&otp, sizeof(otp)); &otp, sizeof(otp));
if (ret != sizeof(otp)) { if (ret != sizeof(otp)) {

View File

@ -26,6 +26,7 @@ obj-$(CONFIG_PHYLIB) += miiphyutil.o
obj-$(CONFIG_USB_HOST) += usb.o usb_hub.o obj-$(CONFIG_USB_HOST) += usb.o usb_hub.o
obj-$(CONFIG_USB_GADGET) += usb.o usb_hub.o obj-$(CONFIG_USB_GADGET) += usb.o usb_hub.o
obj-$(CONFIG_USB_STORAGE) += usb_storage.o obj-$(CONFIG_USB_STORAGE) += usb_storage.o
obj-$(CONFIG_USB_ONBOARD_HUB) += usb_onboard_hub.o
# others # others
obj-$(CONFIG_CONSOLE_MUX) += iomux.o obj-$(CONFIG_CONSOLE_MUX) += iomux.o

62
common/usb_onboard_hub.c Normal file
View File

@ -0,0 +1,62 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Driver for onboard USB hubs
*
* Copyright (C) 2022, STMicroelectronics - All Rights Reserved
*
* Mostly inspired by Linux kernel v6.1 onboard_usb_hub driver
*/
#include <common.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <power/regulator.h>
struct onboard_hub {
struct udevice *vdd;
};
static int usb_onboard_hub_probe(struct udevice *dev)
{
struct onboard_hub *hub = dev_get_priv(dev);
int ret;
ret = device_get_supply_regulator(dev, "vdd-supply", &hub->vdd);
if (ret) {
dev_err(dev, "can't get vdd-supply: %d\n", ret);
return ret;
}
ret = regulator_set_enable_if_allowed(hub->vdd, true);
if (ret)
dev_err(dev, "can't enable vdd-supply: %d\n", ret);
return ret;
}
static int usb_onboard_hub_remove(struct udevice *dev)
{
struct onboard_hub *hub = dev_get_priv(dev);
int ret;
ret = regulator_set_enable_if_allowed(hub->vdd, false);
if (ret)
dev_err(dev, "can't disable vdd-supply: %d\n", ret);
return ret;
}
static const struct udevice_id usb_onboard_hub_ids[] = {
/* Use generic usbVID,PID dt-bindings (usb-device.yaml) */
{ .compatible = "usb424,2514" }, /* USB2514B USB 2.0 */
{ }
};
U_BOOT_DRIVER(usb_onboard_hub) = {
.name = "usb_onboard_hub",
.id = UCLASS_USB_HUB,
.probe = usb_onboard_hub_probe,
.remove = usb_onboard_hub_remove,
.of_match = usb_onboard_hub_ids,
.priv_auto = sizeof(struct onboard_hub),
};

View File

@ -7,6 +7,7 @@ CONFIG_DEFAULT_DEVICE_TREE="stm32mp135f-dk"
CONFIG_SYS_PROMPT="STM32MP> " CONFIG_SYS_PROMPT="STM32MP> "
CONFIG_STM32MP13x=y CONFIG_STM32MP13x=y
CONFIG_DDR_CACHEABLE_SIZE=0x10000000 CONFIG_DDR_CACHEABLE_SIZE=0x10000000
CONFIG_CMD_STM32KEY=y
CONFIG_TARGET_ST_STM32MP13x=y CONFIG_TARGET_ST_STM32MP13x=y
CONFIG_ENV_OFFSET_REDUND=0x940000 CONFIG_ENV_OFFSET_REDUND=0x940000
# CONFIG_ARMV7_NONSEC is not set # CONFIG_ARMV7_NONSEC is not set
@ -26,6 +27,7 @@ CONFIG_CMD_MEMINFO=y
CONFIG_CMD_MEMTEST=y CONFIG_CMD_MEMTEST=y
CONFIG_CMD_UNZIP=y CONFIG_CMD_UNZIP=y
CONFIG_CMD_CLK=y CONFIG_CMD_CLK=y
CONFIG_CMD_FUSE=y
CONFIG_CMD_GPIO=y CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y CONFIG_CMD_I2C=y
CONFIG_CMD_LSBLK=y CONFIG_CMD_LSBLK=y

View File

@ -167,6 +167,7 @@ CONFIG_USB=y
CONFIG_DM_USB_GADGET=y CONFIG_DM_USB_GADGET=y
CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_EHCI_GENERIC=y
CONFIG_USB_ONBOARD_HUB=y
CONFIG_USB_GADGET=y CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
CONFIG_USB_GADGET_VENDOR_NUM=0x0483 CONFIG_USB_GADGET_VENDOR_NUM=0x0483

View File

@ -143,6 +143,7 @@ CONFIG_USB=y
CONFIG_DM_USB_GADGET=y CONFIG_DM_USB_GADGET=y
CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_EHCI_GENERIC=y
CONFIG_USB_ONBOARD_HUB=y
CONFIG_USB_GADGET=y CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
CONFIG_USB_GADGET_VENDOR_NUM=0x0483 CONFIG_USB_GADGET_VENDOR_NUM=0x0483

View File

@ -143,6 +143,7 @@ CONFIG_USB=y
CONFIG_DM_USB_GADGET=y CONFIG_DM_USB_GADGET=y
CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_EHCI_GENERIC=y
CONFIG_USB_ONBOARD_HUB=y
CONFIG_USB_GADGET=y CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
CONFIG_USB_GADGET_VENDOR_NUM=0x0483 CONFIG_USB_GADGET_VENDOR_NUM=0x0483

View File

@ -620,7 +620,7 @@ Prerequisite: check if a MAC address isn't yet programmed in OTP
STM32MP> env print ethaddr STM32MP> env print ethaddr
## Error: "ethaddr" not defined ## Error: "ethaddr" not defined
3) check lock status of fuse 57 & 58 (at 0x39, 0=unlocked, 1=locked):: 3) check lock status of fuse 57 & 58 (at 0x39, 0=unlocked, 0x40000000=locked)::
STM32MP> fuse sense 0 0x10000039 2 STM32MP> fuse sense 0 0x10000039 2
Sensing bank 0: Sensing bank 0:
@ -640,11 +640,11 @@ Example to set mac address "12:34:56:78:9a:bc"
3) Lock OTP:: 3) Lock OTP::
STM32MP> fuse prog 0 0x10000039 1 1 STM32MP> fuse prog 0 0x10000039 0x40000000 0x40000000
STM32MP> fuse sense 0 0x10000039 2 STM32MP> fuse sense 0 0x10000039 2
Sensing bank 0: Sensing bank 0:
Word 0x10000039: 00000001 00000001 Word 0x10000039: 40000000 40000000
4) next REBOOT, in the trace:: 4) next REBOOT, in the trace::

View File

@ -33,8 +33,11 @@
#define STM32H7_ADRDY BIT(0) #define STM32H7_ADRDY BIT(0)
/* STM32H7_ADC_CR - bit fields */ /* STM32H7_ADC_CR - bit fields */
#define STM32H7_ADCAL BIT(31)
#define STM32H7_ADCALDIF BIT(30)
#define STM32H7_DEEPPWD BIT(29) #define STM32H7_DEEPPWD BIT(29)
#define STM32H7_ADVREGEN BIT(28) #define STM32H7_ADVREGEN BIT(28)
#define STM32H7_ADCALLIN BIT(16)
#define STM32H7_BOOST BIT(8) #define STM32H7_BOOST BIT(8)
#define STM32H7_ADSTART BIT(2) #define STM32H7_ADSTART BIT(2)
#define STM32H7_ADDIS BIT(1) #define STM32H7_ADDIS BIT(1)
@ -65,14 +68,56 @@ struct stm32_adc {
const struct stm32_adc_cfg *cfg; const struct stm32_adc_cfg *cfg;
}; };
static void stm32_adc_enter_pwr_down(struct udevice *dev)
{
struct stm32_adc *adc = dev_get_priv(dev);
clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
/* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
}
static int stm32_adc_exit_pwr_down(struct udevice *dev)
{
struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
struct stm32_adc *adc = dev_get_priv(dev);
int ret;
u32 val;
/* return immediately if ADC is not in deep power down mode */
if (!(readl(adc->regs + STM32H7_ADC_CR) & STM32H7_DEEPPWD))
return 0;
/* Exit deep power down, then enable ADC voltage regulator */
clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADVREGEN);
if (common->rate > STM32H7_BOOST_CLKRATE)
setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
/* Wait for startup time */
if (!adc->cfg->has_vregready) {
udelay(20);
return 0;
}
ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
val & STM32MP1_VREGREADY,
STM32_ADC_TIMEOUT_US);
if (ret < 0) {
stm32_adc_enter_pwr_down(dev);
dev_err(dev, "Failed to enable vreg: %d\n", ret);
}
return ret;
}
static int stm32_adc_stop(struct udevice *dev) static int stm32_adc_stop(struct udevice *dev)
{ {
struct stm32_adc *adc = dev_get_priv(dev); struct stm32_adc *adc = dev_get_priv(dev);
setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADDIS); setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADDIS);
clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST); stm32_adc_enter_pwr_down(dev);
/* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
adc->active_channel = -1; adc->active_channel = -1;
return 0; return 0;
@ -81,30 +126,13 @@ static int stm32_adc_stop(struct udevice *dev)
static int stm32_adc_start_channel(struct udevice *dev, int channel) static int stm32_adc_start_channel(struct udevice *dev, int channel)
{ {
struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
struct stm32_adc *adc = dev_get_priv(dev); struct stm32_adc *adc = dev_get_priv(dev);
int ret; int ret;
u32 val; u32 val;
/* Exit deep power down, then enable ADC voltage regulator */ ret = stm32_adc_exit_pwr_down(dev);
clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD); if (ret < 0)
setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADVREGEN); return ret;
if (common->rate > STM32H7_BOOST_CLKRATE)
setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
/* Wait for startup time */
if (!adc->cfg->has_vregready) {
udelay(20);
} else {
ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
val & STM32MP1_VREGREADY,
STM32_ADC_TIMEOUT_US);
if (ret < 0) {
stm32_adc_stop(dev);
dev_err(dev, "Failed to enable vreg: %d\n", ret);
return ret;
}
}
/* Only use single ended channels */ /* Only use single ended channels */
writel(0, adc->regs + STM32H7_ADC_DIFSEL); writel(0, adc->regs + STM32H7_ADC_DIFSEL);
@ -162,6 +190,64 @@ static int stm32_adc_channel_data(struct udevice *dev, int channel,
return 0; return 0;
} }
/**
* Fixed timeout value for ADC calibration.
* worst cases:
* - low clock frequency (0.12 MHz min)
* - maximum prescalers
* Calibration requires:
* - 16384 ADC clock cycle for the linear calibration
* - 20 ADC clock cycle for the offset calibration
*
* Set to 100ms for now
*/
#define STM32H7_ADC_CALIB_TIMEOUT_US 100000
static int stm32_adc_selfcalib(struct udevice *dev)
{
struct stm32_adc *adc = dev_get_priv(dev);
int ret;
u32 val;
/*
* Select calibration mode:
* - Offset calibration for single ended inputs
* - No linearity calibration. Done in next step.
*/
clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCALDIF | STM32H7_ADCALLIN);
/* Start calibration, then wait for completion */
setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCAL);
ret = readl_poll_sleep_timeout(adc->regs + STM32H7_ADC_CR, val,
!(val & STM32H7_ADCAL), 100,
STM32H7_ADC_CALIB_TIMEOUT_US);
if (ret) {
dev_err(dev, "calibration failed\n");
goto out;
}
/*
* Select calibration mode, then start calibration:
* - Offset calibration for differential input
* - Linearity calibration (needs to be done only once for single/diff)
* will run simultaneously with offset calibration.
*/
setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCALDIF | STM32H7_ADCALLIN);
/* Start calibration, then wait for completion */
setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCAL);
ret = readl_poll_sleep_timeout(adc->regs + STM32H7_ADC_CR, val,
!(val & STM32H7_ADCAL), 100,
STM32H7_ADC_CALIB_TIMEOUT_US);
if (ret)
dev_err(dev, "calibration failed\n");
out:
clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCALDIF | STM32H7_ADCALLIN);
return ret;
}
static int stm32_adc_get_legacy_chan_count(struct udevice *dev) static int stm32_adc_get_legacy_chan_count(struct udevice *dev)
{ {
int ret; int ret;
@ -272,7 +358,7 @@ static int stm32_adc_probe(struct udevice *dev)
struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev)); struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
struct stm32_adc *adc = dev_get_priv(dev); struct stm32_adc *adc = dev_get_priv(dev);
int offset; int offset, ret;
offset = dev_read_u32_default(dev, "reg", -ENODATA); offset = dev_read_u32_default(dev, "reg", -ENODATA);
if (offset < 0) { if (offset < 0) {
@ -287,7 +373,19 @@ static int stm32_adc_probe(struct udevice *dev)
uc_pdata->vdd_microvolts = common->vref_uv; uc_pdata->vdd_microvolts = common->vref_uv;
uc_pdata->vss_microvolts = 0; uc_pdata->vss_microvolts = 0;
return stm32_adc_chan_of_init(dev); ret = stm32_adc_chan_of_init(dev);
if (ret < 0)
return ret;
ret = stm32_adc_exit_pwr_down(dev);
if (ret < 0)
return ret;
ret = stm32_adc_selfcalib(dev);
if (ret)
stm32_adc_enter_pwr_down(dev);
return ret;
} }
static const struct adc_ops stm32_adc_ops = { static const struct adc_ops stm32_adc_ops = {

View File

@ -105,6 +105,16 @@ config USB_KEYBOARD
Say Y here if you want to use a USB keyboard for U-Boot command line Say Y here if you want to use a USB keyboard for U-Boot command line
input. input.
config USB_ONBOARD_HUB
bool "Onboard USB hub support"
depends on DM_USB
---help---
Say Y here if you want to support discrete onboard USB hubs that
don't require an additional control bus for initialization, but
need some non-trivial form of initialization, such as enabling a
power regulator. An example for such a hub is the Microchip
USB2514B.
if USB_KEYBOARD if USB_KEYBOARD
config USB_KEYBOARD_FN_KEYS config USB_KEYBOARD_FN_KEYS

View File

@ -271,19 +271,23 @@ int usb_init(void)
/* init low_level USB */ /* init low_level USB */
printf("Bus %s: ", bus->name); printf("Bus %s: ", bus->name);
#ifdef CONFIG_SANDBOX
/* /*
* For Sandbox, we need scan the device tree each time when we * For Sandbox, we need scan the device tree each time when we
* start the USB stack, in order to re-create the emulated USB * start the USB stack, in order to re-create the emulated USB
* devices and bind drivers for them before we actually do the * devices and bind drivers for them before we actually do the
* driver probe. * driver probe.
*
* For USB onboard HUB, we need to do some non-trivial init
* like enabling a power regulator, before enumeration.
*/ */
ret = dm_scan_fdt_dev(bus); if (IS_ENABLED(CONFIG_SANDBOX) ||
if (ret) { IS_ENABLED(CONFIG_USB_ONBOARD_HUB)) {
printf("Sandbox USB device scan failed (%d)\n", ret); ret = dm_scan_fdt_dev(bus);
continue; if (ret) {
printf("USB device scan from fdt failed (%d)", ret);
continue;
}
} }
#endif
ret = device_probe(bus); ret = device_probe(bus);
if (ret == -ENODEV) { /* No such device. */ if (ret == -ENODEV) { /* No such device. */