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:
commit
fe4c21de4f
@ -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>,
|
||||||
|
@ -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"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
|
@ -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"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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" },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
@ -609,6 +772,7 @@ U_BOOT_DRIVER(stm32mp_bsec) = {
|
|||||||
.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,
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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)) {
|
||||||
|
@ -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
62
common/usb_onboard_hub.c
Normal 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),
|
||||||
|
};
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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::
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
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;
|
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 = {
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
if (IS_ENABLED(CONFIG_SANDBOX) ||
|
||||||
|
IS_ENABLED(CONFIG_USB_ONBOARD_HUB)) {
|
||||||
ret = dm_scan_fdt_dev(bus);
|
ret = dm_scan_fdt_dev(bus);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printf("Sandbox USB device scan failed (%d)\n", ret);
|
printf("USB device scan from fdt failed (%d)", ret);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
|
||||||
ret = device_probe(bus);
|
ret = device_probe(bus);
|
||||||
if (ret == -ENODEV) { /* No such device. */
|
if (ret == -ENODEV) { /* No such device. */
|
||||||
|
Loading…
Reference in New Issue
Block a user