diff options
49 files changed, 929 insertions, 433 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 13ba774a48..cb7ec58079 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -817,15 +817,11 @@ config ARCH_SOCFPGA select SPL_DM_RESET if DM_RESET select SPL_DM_SERIAL select SPL_LIBCOMMON_SUPPORT - select SPL_LIBDISK_SUPPORT select SPL_LIBGENERIC_SUPPORT - select SPL_MMC_SUPPORT if DM_MMC select SPL_NAND_SUPPORT if SPL_NAND_DENALI select SPL_OF_CONTROL select SPL_SEPARATE_BSS if TARGET_SOCFPGA_STRATIX10 select SPL_SERIAL_SUPPORT - select SPL_SPI_FLASH_SUPPORT if SPL_SPI_SUPPORT - select SPL_SPI_SUPPORT if DM_SPI select SPL_WATCHDOG_SUPPORT select SUPPORT_SPL select SYS_NS16550 @@ -836,8 +832,12 @@ config ARCH_SOCFPGA imply DM_SPI imply DM_SPI_FLASH imply FAT_WRITE + imply SPL_LIBDISK_SUPPORT + imply SPL_MMC_SUPPORT imply SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION imply SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE + imply SPL_SPI_FLASH_SUPPORT + imply SPL_SPI_SUPPORT config ARCH_SUNXI bool "Support sunxi (Allwinner) SoCs" @@ -932,6 +932,7 @@ config ARCH_ZYNQMP_R5 select DM_SERIAL select OF_CONTROL imply CMD_DM + imply DM_USB_GADGET config ARCH_ZYNQMP bool "Xilinx ZynqMP based platform" @@ -949,6 +950,7 @@ config ARCH_ZYNQMP imply CMD_DM imply FAT_WRITE imply MP + imply DM_USB_GADGET config TEGRA bool "NVIDIA Tegra" diff --git a/arch/arm/dts/omap5-u-boot.dtsi b/arch/arm/dts/omap5-u-boot.dtsi index 30833a3cc9..1eb50cd438 100644 --- a/arch/arm/dts/omap5-u-boot.dtsi +++ b/arch/arm/dts/omap5-u-boot.dtsi @@ -15,6 +15,10 @@ ocp { u-boot,dm-spl; + ocp2scp@4a080000 { + compatible = "ti,omap-ocp2scp", "simple-bus"; + }; + ocp2scp@4a090000 { compatible = "ti,omap-ocp2scp", "simple-bus"; }; diff --git a/arch/arm/mach-rmobile/cpu_info.c b/arch/arm/mach-rmobile/cpu_info.c index 65a9ca8c01..aa5be52dfd 100644 --- a/arch/arm/mach-rmobile/cpu_info.c +++ b/arch/arm/mach-rmobile/cpu_info.c @@ -7,8 +7,6 @@ #include <asm/io.h> #include <linux/ctype.h> -/* R-Car Gen3 caches are enabled in memmap-gen3.c */ -#ifndef CONFIG_RCAR_GEN3 #ifdef CONFIG_ARCH_CPU_INIT int arch_cpu_init(void) { @@ -17,6 +15,8 @@ int arch_cpu_init(void) } #endif +/* R-Car Gen3 D-cache is enabled in memmap-gen3.c */ +#ifndef CONFIG_RCAR_GEN3 #ifndef CONFIG_SYS_DCACHE_OFF void enable_caches(void) { diff --git a/arch/arm/mach-rmobile/memmap-gen3.c b/arch/arm/mach-rmobile/memmap-gen3.c index 7e29ccc351..1a9eb72bb9 100644 --- a/arch/arm/mach-rmobile/memmap-gen3.c +++ b/arch/arm/mach-rmobile/memmap-gen3.c @@ -21,7 +21,13 @@ static struct mm_region gen3_mem_map[GEN3_NR_REGIONS] = { }, { .virt = 0x40000000UL, .phys = 0x40000000UL, - .size = 0x80000000UL, + .size = 0x03F00000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + .virt = 0x47E00000UL, + .phys = 0x47E00000UL, + .size = 0x78200000UL, .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE }, { @@ -76,8 +82,16 @@ void enable_caches(void) /* Mark memory reserved by ATF as cacheable too. */ if (start == 0x48000000) { - start = 0x40000000ULL; - size += 0x08000000ULL; + /* Unmark protection area (0x43F00000 to 0x47DFFFFF) */ + gen3_mem_map[i].virt = 0x40000000ULL; + gen3_mem_map[i].phys = 0x40000000ULL; + gen3_mem_map[i].size = 0x03F00000ULL; + gen3_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE; + i++; + + start = 0x47E00000ULL; + size += 0x00200000ULL; } gen3_mem_map[i].virt = start; @@ -126,6 +140,8 @@ void enable_caches(void) gen3_mem_map[i].attrs = 0; } - icache_enable(); + if (!icache_status()) + icache_enable(); + dcache_enable(); } diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 082fcec3f9..6b1c2692ba 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -460,6 +460,8 @@ test4 { compatible = "denx,u-boot-probe-test"; + first-syscon = <&syscon0>; + second-sys-ctrl = <&another_system_controller>; }; }; @@ -540,12 +542,12 @@ }; }; - syscon@0 { + syscon0: syscon@0 { compatible = "sandbox,syscon0"; reg = <0x10 16>; }; - syscon@1 { + another_system_controller: syscon@1 { compatible = "sandbox,syscon1"; reg = <0x20 5 0x28 6 diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index a1c18d26e1..e052093775 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -729,13 +729,22 @@ config PCIE_ECAM_SIZE maximum number of PCI buses as defined by the PCI specification. config I8259_PIC - bool + bool "Enable Intel 8259 compatible interrupt controller" default y help Intel 8259 ISA compatible chipset incorporates two 8259 (master and slave) interrupt controllers. Include this to have U-Boot set up the interrupt correctly. +config APIC + bool "Enable Intel Advanced Programmable Interrupt Controller" + default y + help + The (A)dvanced (P)rogrammable (I)nterrupt (C)ontroller is responsible + for catching interrupts and distributing them to one or more CPU + cores. In most cases there are some LAPICs (local) for each core and + one I/O APIC. This conjunction is found on most modern x86 systems. + config PINCTRL_ICH6 bool help diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index f862d8c071..54668aab24 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -35,7 +35,7 @@ obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/ obj-$(CONFIG_INTEL_QUARK) += quark/ obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/ obj-$(CONFIG_INTEL_TANGIER) += tangier/ -obj-y += lapic.o ioapic.o +obj-$(CONFIG_APIC) += lapic.o ioapic.o obj-y += irq.o ifndef CONFIG_$(SPL_)X86_64 obj-$(CONFIG_SMP) += mp_init.o diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index aaf0d07192..4c6ed0bfb2 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -77,7 +77,8 @@ int last_stage_init(void) timestamp_add_to_bootstage(); /* start usb so that usb keyboard can be used as input device */ - usb_init(); + if (CONFIG_IS_ENABLED(USB_KEYBOARD)) + usb_init(); board_final_cleanup(); diff --git a/arch/x86/cpu/efi/payload.c b/arch/x86/cpu/efi/payload.c index c323c7b19a..225aef7bf6 100644 --- a/arch/x86/cpu/efi/payload.c +++ b/arch/x86/cpu/efi/payload.c @@ -166,7 +166,8 @@ int reserve_arch(void) int last_stage_init(void) { /* start usb so that usb keyboard can be used as input device */ - usb_init(); + if (CONFIG_IS_ENABLED(USB_KEYBOARD)) + usb_init(); return 0; } diff --git a/arch/x86/cpu/i386/interrupt.c b/arch/x86/cpu/i386/interrupt.c index ed8423e079..1ea415b876 100644 --- a/arch/x86/cpu/i386/interrupt.c +++ b/arch/x86/cpu/i386/interrupt.c @@ -264,7 +264,9 @@ int interrupt_init(void) i8259_init(); #endif +#ifdef CONFIG_APIC lapic_setup(); +#endif /* Initialize core interrupt and exception functionality of CPU */ cpu_init_interrupts(); diff --git a/arch/x86/include/asm/arch-tangier/acpi/platform.asl b/arch/x86/include/asm/arch-tangier/acpi/platform.asl index 7abea4bb96..353b879918 100644 --- a/arch/x86/include/asm/arch-tangier/acpi/platform.asl +++ b/arch/x86/include/asm/arch-tangier/acpi/platform.asl @@ -21,6 +21,19 @@ Method(_WAK, 1) Return (Package() {0, 0}) } +Scope (_SB) +{ + /* Real Time Clock */ + Device (RTC0) + { + Name (_HID, EisaId ("PNP0B00")) + Name (_CRS, ResourceTemplate() + { + IO(Decode16, 0x70, 0x70, 0x01, 0x08) + }) + } +} + /* ACPI global NVS */ #include "global_nvs.asl" diff --git a/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl index 48193ba957..e166e510cb 100644 --- a/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl +++ b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl @@ -295,16 +295,16 @@ Device (PCI0) Method (_CRS, 0, Serialized) { - Name (RBUF, ResourceTemplate () + Name (RBUF, ResourceTemplate() { - UartSerialBus (0x0001C200, DataBitsEight, StopBitsOne, + UartSerialBus(0x0001C200, DataBitsEight, StopBitsOne, 0xFC, LittleEndian, ParityTypeNone, FlowControlHardware, 0x20, 0x20, "\\_SB.PCI0.HSU0", 0, ResourceConsumer, , ) - GpioInt (Level, ActiveHigh, Exclusive, PullNone, 0, + GpioInt(Level, ActiveHigh, Exclusive, PullNone, 0, "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 185 } - GpioIo (Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly, + GpioIo(Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly, "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 184 } - GpioIo (Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly, + GpioIo(Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly, "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 71 } }) Return (RBUF) @@ -328,7 +328,7 @@ Device (FLIS) Name (_DDN, "Intel Merrifield Family-Level Interface Shim") Name (RBUF, ResourceTemplate() { - Memory32Fixed(ReadWrite, 0xFF0C0000, 0x00008000, ) + Memory32Fixed(ReadWrite, 0xFF0C0000, 0x00008000) PinGroup("spi5", ResourceProducer, ) { 90, 91, 92, 93, 94, 95, 96 } PinGroup("uart0", ResourceProducer, ) { 115, 116, 117, 118 } PinGroup("uart1", ResourceProducer, ) { 119, 120, 121, 122 } diff --git a/arch/x86/lib/interrupts.c b/arch/x86/lib/interrupts.c index 297067df71..39f8deaed1 100644 --- a/arch/x86/lib/interrupts.c +++ b/arch/x86/lib/interrupts.c @@ -64,7 +64,8 @@ void irq_install_handler(int irq, interrupt_handler_t *handler, void *arg) irq_handlers[irq].arg = arg; irq_handlers[irq].count = 0; - unmask_irq(irq); + if (CONFIG_IS_ENABLED(I8259_PIC)) + unmask_irq(irq); if (status) enable_interrupts(); @@ -83,7 +84,8 @@ void irq_free_handler(int irq) status = disable_interrupts(); - mask_irq(irq); + if (CONFIG_IS_ENABLED(I8259_PIC)) + mask_irq(irq); irq_handlers[irq].handler = NULL; irq_handlers[irq].arg = NULL; @@ -104,14 +106,16 @@ void do_irq(int hw_irq) } if (irq_handlers[irq].handler) { - mask_irq(irq); + if (CONFIG_IS_ENABLED(I8259_PIC)) + mask_irq(irq); irq_handlers[irq].handler(irq_handlers[irq].arg); irq_handlers[irq].count++; - unmask_irq(irq); - specific_eoi(irq); - + if (CONFIG_IS_ENABLED(I8259_PIC)) { + unmask_irq(irq); + specific_eoi(irq); + } } else { if ((irq & 7) != 7) { spurious_irq_cnt++; diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 8e20dc7e43..917f5b18f6 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -665,7 +665,7 @@ int g_dnl_board_usb_cable_connected(void) struct phy phy; int ret; - ret = uclass_get_device(UCLASS_USB_DEV_GENERIC, 0, &dev); + ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, 0, &dev); if (ret) { pr_err("%s: Cannot find USB device\n", __func__); return ret; diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c index 9738beb2b0..7063345dcc 100644 --- a/board/ti/am57xx/board.c +++ b/board/ti/am57xx/board.c @@ -672,6 +672,19 @@ out: return; } +#if CONFIG_IS_ENABLED(DM_USB) && CONFIG_IS_ENABLED(OF_CONTROL) +static int device_okay(const char *path) +{ + int node; + + node = fdt_path_offset(gd->fdt_blob, path); + if (node < 0) + return 0; + + return fdtdec_get_is_enabled(gd->fdt_blob, node); +} +#endif + int board_late_init(void) { setup_board_eeprom_env(); @@ -711,6 +724,12 @@ int board_late_init(void) board_ti_set_ethaddr(2); #endif +#if CONFIG_IS_ENABLED(DM_USB) && CONFIG_IS_ENABLED(OF_CONTROL) + if (device_okay("/ocp/omap_dwc3_1@48880000")) + enable_usb_clocks(0); + if (device_okay("/ocp/omap_dwc3_2@488c0000")) + enable_usb_clocks(1); +#endif return 0; } @@ -861,93 +880,6 @@ int spl_start_uboot(void) } #endif -#ifdef CONFIG_USB_DWC3 -static struct dwc3_device usb_otg_ss2 = { - .maximum_speed = USB_SPEED_HIGH, - .base = DRA7_USB_OTG_SS2_BASE, - .tx_fifo_resize = false, - .index = 1, -}; - -static struct dwc3_omap_device usb_otg_ss2_glue = { - .base = (void *)DRA7_USB_OTG_SS2_GLUE_BASE, - .utmi_mode = DWC3_OMAP_UTMI_MODE_SW, - .index = 1, -}; - -static struct ti_usb_phy_device usb_phy2_device = { - .usb2_phy_power = (void *)DRA7_USB2_PHY2_POWER, - .index = 1, -}; - -int usb_gadget_handle_interrupts(int index) -{ - u32 status; - - status = dwc3_omap_uboot_interrupt_status(index); - if (status) - dwc3_uboot_handle_interrupt(index); - - return 0; -} -#endif /* CONFIG_USB_DWC3 */ - -#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP) -int board_usb_init(int index, enum usb_init_type init) -{ - enable_usb_clocks(index); - switch (index) { - case 0: - if (init == USB_INIT_DEVICE) { - printf("port %d can't be used as device\n", index); - disable_usb_clocks(index); - return -EINVAL; - } - break; - case 1: - if (init == USB_INIT_DEVICE) { -#ifdef CONFIG_USB_DWC3 - usb_otg_ss2.dr_mode = USB_DR_MODE_PERIPHERAL; - usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID; - ti_usb_phy_uboot_init(&usb_phy2_device); - dwc3_omap_uboot_init(&usb_otg_ss2_glue); - dwc3_uboot_init(&usb_otg_ss2); -#endif - } else { - printf("port %d can't be used as host\n", index); - disable_usb_clocks(index); - return -EINVAL; - } - - break; - default: - printf("Invalid Controller Index\n"); - } - - return 0; -} - -int board_usb_cleanup(int index, enum usb_init_type init) -{ -#ifdef CONFIG_USB_DWC3 - switch (index) { - case 0: - case 1: - if (init == USB_INIT_DEVICE) { - ti_usb_phy_uboot_exit(index); - dwc3_uboot_exit(index); - dwc3_omap_uboot_exit(index); - } - break; - default: - printf("Invalid Controller Index\n"); - } -#endif - disable_usb_clocks(index); - return 0; -} -#endif /* defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP) */ - #ifdef CONFIG_DRIVER_TI_CPSW /* Delay value to add to calibrated value */ diff --git a/board/ti/dra7xx/evm.c b/board/ti/dra7xx/evm.c index bbe54450ae..d69641e3a0 100644 --- a/board/ti/dra7xx/evm.c +++ b/board/ti/dra7xx/evm.c @@ -646,6 +646,19 @@ int dram_init_banksize(void) return 0; } +#if CONFIG_IS_ENABLED(DM_USB) && CONFIG_IS_ENABLED(OF_CONTROL) +static int device_okay(const char *path) +{ + int node; + + node = fdt_path_offset(gd->fdt_blob, path); + if (node < 0) + return 0; + + return fdtdec_get_is_enabled(gd->fdt_blob, node); +} +#endif + int board_late_init(void) { #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG @@ -685,6 +698,12 @@ int board_late_init(void) if (board_is_dra71x_evm()) palmas_i2c_write_u8(LP873X_I2C_SLAVE_ADDR, 0x9, 0x7); #endif +#if CONFIG_IS_ENABLED(DM_USB) && CONFIG_IS_ENABLED(OF_CONTROL) + if (device_okay("/ocp/omap_dwc3_1@48880000")) + enable_usb_clocks(0); + if (device_okay("/ocp/omap_dwc3_2@488c0000")) + enable_usb_clocks(1); +#endif return 0; } @@ -896,110 +915,6 @@ const struct mmc_platform_fixups *platform_fixups_mmc(uint32_t addr) } #endif -#ifdef CONFIG_USB_DWC3 -static struct dwc3_device usb_otg_ss1 = { - .maximum_speed = USB_SPEED_SUPER, - .base = DRA7_USB_OTG_SS1_BASE, - .tx_fifo_resize = false, - .index = 0, -}; - -static struct dwc3_omap_device usb_otg_ss1_glue = { - .base = (void *)DRA7_USB_OTG_SS1_GLUE_BASE, - .utmi_mode = DWC3_OMAP_UTMI_MODE_SW, - .index = 0, -}; - -static struct ti_usb_phy_device usb_phy1_device = { - .pll_ctrl_base = (void *)DRA7_USB3_PHY1_PLL_CTRL, - .usb2_phy_power = (void *)DRA7_USB2_PHY1_POWER, - .usb3_phy_power = (void *)DRA7_USB3_PHY1_POWER, - .index = 0, -}; - -static struct dwc3_device usb_otg_ss2 = { - .maximum_speed = USB_SPEED_SUPER, - .base = DRA7_USB_OTG_SS2_BASE, - .tx_fifo_resize = false, - .index = 1, -}; - -static struct dwc3_omap_device usb_otg_ss2_glue = { - .base = (void *)DRA7_USB_OTG_SS2_GLUE_BASE, - .utmi_mode = DWC3_OMAP_UTMI_MODE_SW, - .index = 1, -}; - -static struct ti_usb_phy_device usb_phy2_device = { - .usb2_phy_power = (void *)DRA7_USB2_PHY2_POWER, - .index = 1, -}; - -int board_usb_init(int index, enum usb_init_type init) -{ - enable_usb_clocks(index); - switch (index) { - case 0: - if (init == USB_INIT_DEVICE) { - usb_otg_ss1.dr_mode = USB_DR_MODE_PERIPHERAL; - usb_otg_ss1_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID; - } else { - usb_otg_ss1.dr_mode = USB_DR_MODE_HOST; - usb_otg_ss1_glue.vbus_id_status = OMAP_DWC3_ID_GROUND; - } - - ti_usb_phy_uboot_init(&usb_phy1_device); - dwc3_omap_uboot_init(&usb_otg_ss1_glue); - dwc3_uboot_init(&usb_otg_ss1); - break; - case 1: - if (init == USB_INIT_DEVICE) { - usb_otg_ss2.dr_mode = USB_DR_MODE_PERIPHERAL; - usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID; - } else { - usb_otg_ss2.dr_mode = USB_DR_MODE_HOST; - usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_ID_GROUND; - } - - ti_usb_phy_uboot_init(&usb_phy2_device); - dwc3_omap_uboot_init(&usb_otg_ss2_glue); - dwc3_uboot_init(&usb_otg_ss2); - break; - default: - printf("Invalid Controller Index\n"); - } - - return 0; -} - -int board_usb_cleanup(int index, enum usb_init_type init) -{ - switch (index) { - case 0: - case 1: - ti_usb_phy_uboot_exit(index); - dwc3_uboot_exit(index); - dwc3_omap_uboot_exit(index); - break; - default: - printf("Invalid Controller Index\n"); - } - disable_usb_clocks(index); - return 0; -} - -int usb_gadget_handle_interrupts(int index) -{ - u32 status; - - status = dwc3_omap_uboot_interrupt_status(index); - if (status) - dwc3_uboot_handle_interrupt(index); - - return 0; -} -#endif - #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_OS_BOOT) int spl_start_uboot(void) { diff --git a/cmd/fastboot.c b/cmd/fastboot.c index ae3a5f627f..0be83b78ac 100644 --- a/cmd/fastboot.c +++ b/cmd/fastboot.c @@ -51,7 +51,7 @@ static int do_fastboot_usb(int argc, char *const argv[], return CMD_RET_FAILURE; } - ret = board_usb_init(controller_index, USB_INIT_DEVICE); + ret = usb_gadget_initialize(controller_index); if (ret) { pr_err("USB init failed: %d\n", ret); return CMD_RET_FAILURE; @@ -82,7 +82,7 @@ static int do_fastboot_usb(int argc, char *const argv[], exit: g_dnl_unregister(); g_dnl_clear_detach(); - board_usb_cleanup(controller_index, USB_INIT_DEVICE); + usb_gadget_release(controller_index); return ret; #else diff --git a/cmd/rockusb.c b/cmd/rockusb.c index 8206643b27..e0c1480d6d 100644 --- a/cmd/rockusb.c +++ b/cmd/rockusb.c @@ -33,7 +33,7 @@ static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) dev_index = simple_strtoul(devnum, NULL, 0); rockusb_dev_init(devtype, dev_index); - ret = board_usb_init(controller_index, USB_INIT_DEVICE); + ret = usb_gadget_initialize(controller_index); if (ret) { printf("USB init failed: %d\n", ret); return CMD_RET_FAILURE; @@ -62,7 +62,7 @@ static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) exit: g_dnl_unregister(); g_dnl_clear_detach(); - board_usb_cleanup(controller_index, USB_INIT_DEVICE); + usb_gadget_release(controller_index); return ret; } diff --git a/cmd/thordown.c b/cmd/thordown.c index 2615adad75..ce3660d174 100644 --- a/cmd/thordown.c +++ b/cmd/thordown.c @@ -30,7 +30,7 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) goto done; int controller_index = simple_strtoul(usb_controller, NULL, 0); - ret = board_usb_init(controller_index, USB_INIT_DEVICE); + ret = usb_gadget_initialize(controller_index); if (ret) { pr_err("USB init failed: %d\n", ret); ret = CMD_RET_FAILURE; @@ -55,7 +55,7 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) exit: g_dnl_unregister(); - board_usb_cleanup(controller_index, USB_INIT_DEVICE); + usb_gadget_release(controller_index); done: dfu_free_entities(); diff --git a/cmd/usb_gadget_sdp.c b/cmd/usb_gadget_sdp.c index ba1f66a5de..808ed974fa 100644 --- a/cmd/usb_gadget_sdp.c +++ b/cmd/usb_gadget_sdp.c @@ -20,7 +20,7 @@ static int do_sdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) char *usb_controller = argv[1]; int controller_index = simple_strtoul(usb_controller, NULL, 0); - board_usb_init(controller_index, USB_INIT_DEVICE); + usb_gadget_initialize(controller_index); g_dnl_clear_detach(); g_dnl_register("usb_dnl_sdp"); @@ -37,7 +37,7 @@ static int do_sdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) exit: g_dnl_unregister(); - board_usb_cleanup(controller_index, USB_INIT_DEVICE); + usb_gadget_release(controller_index); return ret; } diff --git a/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c index 0d551141e0..753ae4f42a 100644 --- a/cmd/usb_mass_storage.c +++ b/cmd/usb_mass_storage.c @@ -160,7 +160,7 @@ static int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag, controller_index = (unsigned int)(simple_strtoul( usb_controller, NULL, 0)); - if (board_usb_init(controller_index, USB_INIT_DEVICE)) { + if (usb_gadget_initialize(controller_index)) { pr_err("Couldn't init USB controller.\n"); rc = CMD_RET_FAILURE; goto cleanup_ums_init; @@ -231,7 +231,7 @@ static int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag, cleanup_register: g_dnl_unregister(); cleanup_board: - board_usb_cleanup(controller_index, USB_INIT_DEVICE); + usb_gadget_release(controller_index); cleanup_ums_init: ums_fini(); diff --git a/common/dfu.c b/common/dfu.c index 2620d3238b..44d1484d3d 100644 --- a/common/dfu.c +++ b/common/dfu.c @@ -23,9 +23,9 @@ int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget) bool dfu_reset = false; int ret, i = 0; - ret = board_usb_init(usbctrl_index, USB_INIT_DEVICE); + ret = usb_gadget_initialize(usbctrl_index); if (ret) { - pr_err("board usb init failed\n"); + pr_err("usb_gadget_initialize failed\n"); return CMD_RET_FAILURE; } g_dnl_clear_detach(); @@ -84,7 +84,7 @@ int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget) } exit: g_dnl_unregister(); - board_usb_cleanup(usbctrl_index, USB_INIT_DEVICE); + usb_gadget_release(usbctrl_index); if (dfu_reset) do_reset(NULL, 0, 0, NULL); diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig index 4bcabb8276..aa8283033e 100644 --- a/configs/am57xx_evm_defconfig +++ b/configs/am57xx_evm_defconfig @@ -51,6 +51,7 @@ CONFIG_FASTBOOT_FLASH_MMC_DEV=1 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_MMC_OMAP_HS=y CONFIG_DM_SPI_FLASH=y @@ -62,6 +63,9 @@ CONFIG_PHY_MICREL_KSZ90X1=y CONFIG_DM_ETH=y CONFIG_DRIVER_TI_CPSW=y CONFIG_MII=y +CONFIG_PHY=y +CONFIG_PIPE3_PHY=y +CONFIG_OMAP_USB2_PHY=y CONFIG_DM_PMIC=y CONFIG_PMIC_PALMAS=y CONFIG_DM_REGULATOR=y @@ -71,13 +75,15 @@ CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_TI_QSPI=y CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_SPL_DM_USB=y +CONFIG_DM_USB_GADGET=y +CONFIG_SPL_DM_USB_GADGET=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y -CONFIG_USB_DWC3_OMAP=y -CONFIG_USB_DWC3_PHY_OMAP=y -CONFIG_OMAP_USB_PHY=y +CONFIG_USB_DWC3_GENERIC=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" diff --git a/configs/am57xx_hs_evm_defconfig b/configs/am57xx_hs_evm_defconfig index fd2083f371..09f3774b6d 100644 --- a/configs/am57xx_hs_evm_defconfig +++ b/configs/am57xx_hs_evm_defconfig @@ -54,6 +54,7 @@ CONFIG_FASTBOOT_FLASH_MMC_DEV=1 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_MMC_OMAP_HS=y CONFIG_DM_SPI_FLASH=y @@ -65,6 +66,9 @@ CONFIG_PHY_MICREL_KSZ90X1=y CONFIG_DM_ETH=y CONFIG_DRIVER_TI_CPSW=y CONFIG_MII=y +CONFIG_PHY=y +CONFIG_PIPE3_PHY=y +CONFIG_OMAP_USB2_PHY=y CONFIG_DM_PMIC=y CONFIG_PMIC_PALMAS=y CONFIG_DM_REGULATOR=y @@ -74,13 +78,15 @@ CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_TI_QSPI=y CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_SPL_DM_USB=y +CONFIG_DM_USB_GADGET=y +CONFIG_SPL_DM_USB_GADGET=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y -CONFIG_USB_DWC3_OMAP=y -CONFIG_USB_DWC3_PHY_OMAP=y -CONFIG_OMAP_USB_PHY=y +CONFIG_USB_DWC3_GENERIC=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig index 2ea1d596cc..2b6606f9e2 100644 --- a/configs/dra7xx_evm_defconfig +++ b/configs/dra7xx_evm_defconfig @@ -58,6 +58,7 @@ CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_DM_GPIO=y CONFIG_PCF8575_GPIO=y CONFIG_DM_I2C=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_MMC_IO_VOLTAGE=y CONFIG_MMC_UHS_SUPPORT=y @@ -74,6 +75,7 @@ CONFIG_PHY_GIGE=y CONFIG_MII=y CONFIG_SPL_PHY=y CONFIG_PIPE3_PHY=y +CONFIG_OMAP_USB2_PHY=y CONFIG_PMIC_PALMAS=y CONFIG_PMIC_LP873X=y CONFIG_DM_REGULATOR_FIXED=y @@ -89,14 +91,14 @@ CONFIG_TIMER=y CONFIG_OMAP_TIMER=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_SPL_DM_USB=y +CONFIG_DM_USB_GADGET=y +CONFIG_SPL_DM_USB_GADGET=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_DRA7XX_INDEX=1 CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y -CONFIG_USB_DWC3_OMAP=y -CONFIG_USB_DWC3_PHY_OMAP=y -CONFIG_OMAP_USB_PHY=y +CONFIG_USB_DWC3_GENERIC=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig index 687cc39191..725acb5279 100644 --- a/configs/dra7xx_hs_evm_defconfig +++ b/configs/dra7xx_hs_evm_defconfig @@ -57,6 +57,7 @@ CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_DM_GPIO=y CONFIG_PCF8575_GPIO=y CONFIG_DM_I2C=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_MMC_IO_VOLTAGE=y CONFIG_MMC_UHS_SUPPORT=y @@ -72,6 +73,7 @@ CONFIG_PHY_GIGE=y CONFIG_MII=y CONFIG_SPL_PHY=y CONFIG_PIPE3_PHY=y +CONFIG_OMAP_USB2_PHY=y CONFIG_PMIC_PALMAS=y CONFIG_PMIC_LP873X=y CONFIG_DM_REGULATOR_FIXED=y @@ -87,14 +89,14 @@ CONFIG_TIMER=y CONFIG_OMAP_TIMER=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_SPL_DM_USB=y +CONFIG_DM_USB_GADGET=y +CONFIG_SPL_DM_USB_GADGET=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_DRA7XX_INDEX=1 CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y -CONFIG_USB_DWC3_OMAP=y -CONFIG_USB_DWC3_PHY_OMAP=y -CONFIG_OMAP_USB_PHY=y +CONFIG_USB_DWC3_GENERIC=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig index 5b3bb8eae7..f0221633fa 100644 --- a/configs/evb-rk3328_defconfig +++ b/configs/evb-rk3328_defconfig @@ -49,6 +49,7 @@ CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYSRESET=y CONFIG_USB=y +CONFIG_USB_DWC3=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c index 303e166a69..661cf61d62 100644 --- a/drivers/core/syscon-uclass.c +++ b/drivers/core/syscon-uclass.c @@ -53,6 +53,29 @@ static int syscon_pre_probe(struct udevice *dev) #endif } +struct regmap *syscon_regmap_lookup_by_phandle(struct udevice *dev, + const char *name) +{ + struct udevice *syscon; + struct regmap *r; + int err; + + err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, + name, &syscon); + if (err) { + dev_dbg(dev, "unable to find syscon device\n"); + return ERR_PTR(err); + } + + r = syscon_get_regmap(syscon); + if (!r) { + dev_dbg(dev, "unable to find regmap\n"); + return ERR_PTR(-ENODEV); + } + + return r; +} + int syscon_get_by_driver_data(ulong driver_data, struct udevice **devp) { struct udevice *dev; diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 14d82b93ed..3921e39d7b 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -155,4 +155,13 @@ config MSM8916_USB_PHY This PHY is found on qualcomm dragonboard410c development board. +config OMAP_USB2_PHY + bool "Support OMAP's USB2 PHY" + depends on PHY + depends on SYSCON + help + Support for the OMAP's USB2 PHY. + + This PHY is found on OMAP devices supporting USB2. + endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 8030d599e7..53dd5bd0f7 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_PHY_RCAR_GEN3) += phy-rcar-gen3.o obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o +obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o diff --git a/drivers/phy/omap-usb2-phy.c b/drivers/phy/omap-usb2-phy.c new file mode 100644 index 0000000000..fd20e8c168 --- /dev/null +++ b/drivers/phy/omap-usb2-phy.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * OMAP USB2 PHY LAYER + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + * Written by Jean-Jacques Hiblot <jjhiblot@ti.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <errno.h> +#include <generic-phy.h> +#include <regmap.h> +#include <syscon.h> + +#define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT BIT(0) + +#define OMAP_DEV_PHY_PD BIT(0) +#define OMAP_USB2_PHY_PD BIT(28) + +#define USB2PHY_DISCON_BYP_LATCH BIT(31) +#define USB2PHY_ANA_CONFIG1 (0x4c) + +DECLARE_GLOBAL_DATA_PTR; + +struct omap_usb2_phy { + struct regmap *pwr_regmap; + ulong flags; + void *phy_base; + u32 pwr_reg_offset; +}; + +struct usb_phy_data { + const char *label; + u8 flags; + u32 mask; + u32 power_on; + u32 power_off; +}; + +static const struct usb_phy_data omap5_usb2_data = { + .label = "omap5_usb2", + .flags = 0, + .mask = OMAP_DEV_PHY_PD, + .power_off = OMAP_DEV_PHY_PD, +}; + +static const struct usb_phy_data dra7x_usb2_data = { + .label = "dra7x_usb2", + .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT, + .mask = OMAP_DEV_PHY_PD, + .power_off = OMAP_DEV_PHY_PD, +}; + +static const struct usb_phy_data dra7x_usb2_phy2_data = { + .label = "dra7x_usb2_phy2", + .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT, + .mask = OMAP_USB2_PHY_PD, + .power_off = OMAP_USB2_PHY_PD, +}; + +static const struct udevice_id omap_usb2_id_table[] = { + { + .compatible = "ti,omap5-usb2", + .data = (ulong)&omap5_usb2_data, + }, + { + .compatible = "ti,dra7x-usb2", + .data = (ulong)&dra7x_usb2_data, + }, + { + .compatible = "ti,dra7x-usb2-phy2", + .data = (ulong)&dra7x_usb2_phy2_data, + }, + {}, +}; + +static int omap_usb_phy_power(struct phy *usb_phy, bool on) +{ + struct udevice *dev = usb_phy->dev; + const struct usb_phy_data *data; + const struct omap_usb2_phy *phy = dev_get_priv(dev); + u32 val; + int rc; + + data = (const struct usb_phy_data *)dev_get_driver_data(dev); + if (!data) + return -EINVAL; + + rc = regmap_read(phy->pwr_regmap, phy->pwr_reg_offset, &val); + if (rc) + return rc; + val &= ~data->mask; + if (on) + val |= data->power_on; + else + val |= data->power_off; + rc = regmap_write(phy->pwr_regmap, phy->pwr_reg_offset, val); + if (rc) + return rc; + + return 0; +} + +static int omap_usb2_phy_init(struct phy *usb_phy) +{ + struct udevice *dev = usb_phy->dev; + struct omap_usb2_phy *priv = dev_get_priv(dev); + u32 val; + + if (priv->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) { + /* + * + * Reduce the sensitivity of internal PHY by enabling the + * DISCON_BYP_LATCH of the USB2PHY_ANA_CONFIG1 register. This + * resolves issues with certain devices which can otherwise + * be prone to false disconnects. + * + */ + val = readl(priv->phy_base + USB2PHY_ANA_CONFIG1); + val |= USB2PHY_DISCON_BYP_LATCH; + writel(val, priv->phy_base + USB2PHY_ANA_CONFIG1); + } + + return 0; +} + +static int omap_usb2_phy_power_on(struct phy *usb_phy) +{ + return omap_usb_phy_power(usb_phy, true); +} + +static int omap_usb2_phy_power_off(struct phy *usb_phy) +{ + return omap_usb_phy_power(usb_phy, false); +} + +static int omap_usb2_phy_exit(struct phy *usb_phy) +{ + return omap_usb_phy_power(usb_phy, false); +} + +struct phy_ops omap_usb2_phy_ops = { + .init = omap_usb2_phy_init, + .power_on = omap_usb2_phy_power_on, + .power_off = omap_usb2_phy_power_off, + .exit = omap_usb2_phy_exit, +}; + +int omap_usb2_phy_probe(struct udevice *dev) +{ + int rc; + struct regmap *regmap; + struct omap_usb2_phy *priv = dev_get_priv(dev); + const struct usb_phy_data *data; + u32 tmp[2]; + + data = (const struct usb_phy_data *)dev_get_driver_data(dev); + if (!data) + return -EINVAL; + + if (data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) { + u32 base = dev_read_addr(dev); + + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + priv->phy_base = (void *)base; + priv->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT; + } + + regmap = syscon_regmap_lookup_by_phandle(dev, "syscon-phy-power"); + if (IS_ERR(regmap)) { + printf("can't get regmap (err %ld)\n", PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + priv->pwr_regmap = regmap; + + rc = dev_read_u32_array(dev, "syscon-phy-power", tmp, 2); + if (rc) { + printf("couldn't get power reg. offset (err %d)\n", rc); + return rc; + } + priv->pwr_reg_offset = tmp[1]; + + return 0; +} + +U_BOOT_DRIVER(omap_usb2_phy) = { + .name = "omap_usb2_phy", + .id = UCLASS_PHY, + .of_match = omap_usb2_id_table, + .probe = omap_usb2_phy_probe, + .ops = &omap_usb2_phy_ops, + .priv_auto_alloc_size = sizeof(struct omap_usb2_phy), +}; diff --git a/drivers/phy/ti-pipe3-phy.c b/drivers/phy/ti-pipe3-phy.c index b22bbaf985..e7e78e3c56 100644 --- a/drivers/phy/ti-pipe3-phy.c +++ b/drivers/phy/ti-pipe3-phy.c @@ -141,7 +141,7 @@ static int omap_pipe3_dpll_program(struct omap_pipe3 *pipe3) omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION1, val); val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION2); - val &= ~PLL_SELFREQDCO_MASK; + val &= ~(PLL_SELFREQDCO_MASK | PLL_IDLE); val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION2, val); @@ -265,10 +265,13 @@ static int pipe3_exit(struct phy *phy) return -EBUSY; } - val = readl(pipe3->pll_reset_reg); - writel(val | SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg); - mdelay(1); - writel(val & ~SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg); + if (pipe3->pll_reset_reg) { + val = readl(pipe3->pll_reset_reg); + writel(val | SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg); + mdelay(1); + writel(val & ~SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg); + } + return 0; } @@ -331,9 +334,11 @@ static int pipe3_phy_probe(struct udevice *dev) if (!pipe3->power_reg) return -EINVAL; - pipe3->pll_reset_reg = get_reg(dev, "syscon-pllreset"); - if (!pipe3->pll_reset_reg) - return -EINVAL; + if (device_is_compatible(dev, "ti,phy-pipe3-sata")) { + pipe3->pll_reset_reg = get_reg(dev, "syscon-pllreset"); + if (!pipe3->pll_reset_reg) + return -EINVAL; + } pipe3->dpll_map = (struct pipe3_dpll_map *)dev_get_driver_data(dev); @@ -350,8 +355,19 @@ static struct pipe3_dpll_map dpll_map_sata[] = { { }, /* Terminator */ }; +static struct pipe3_dpll_map dpll_map_usb[] = { + {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ + {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ + {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ + {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ + {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ + {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ + { }, /* Terminator */ +}; + static const struct udevice_id pipe3_phy_ids[] = { { .compatible = "ti,phy-pipe3-sata", .data = (ulong)&dpll_map_sata }, + { .compatible = "ti,omap-usb3", .data = (ulong)&dpll_map_usb}, { } }; diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index d456beb43f..98f83433be 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -52,6 +52,20 @@ config SPL_DM_USB depends on DM_USB default y +config DM_USB_GADGET + bool "Enable driver model for USB Gadget" + depends on DM_USB + help + Enable driver model for USB Gadget (Peripheral + mode) + +config SPL_DM_USB_GADGET + bool "Enable driver model for USB Gadget in sPL" + depends on SPL_DM_USB + help + Enable driver model for USB Gadget in SPL + (Peripheral mode) + source "drivers/usb/host/Kconfig" source "drivers/usb/dwc3/Kconfig" diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 943b7630eb..bbd8105c06 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -38,10 +38,11 @@ config USB_DWC3_OMAP Say 'Y' here if you have one such device config USB_DWC3_GENERIC - bool "Xilinx ZynqMP and similar Platforms" - depends on DM_USB && USB_DWC3 + bool "Generic implementation of a DWC3 wrapper (aka dwc3 glue)" + depends on DM_USB && USB_DWC3 && MISC help - Some platforms can reuse this DWC3 generic implementation. + Select this for Xilinx ZynqMP and similar Platforms. + This wrapper supports Host and Peripheral operation modes. config USB_DWC3_UNIPHIER bool "DesignWare USB3 Host Support on UniPhier Platforms" diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index f1ca6191ce..56e2a046bf 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -19,7 +19,7 @@ #include <asm/dma-mapping.h> #include <linux/ioport.h> #include <dm.h> - +#include <generic-phy.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> @@ -789,8 +789,92 @@ MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); -#if CONFIG_IS_ENABLED(DM_USB) +#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB) +int dwc3_setup_phy(struct udevice *dev, struct phy **array, int *num_phys) +{ + int i, ret, count; + struct phy *usb_phys; + + /* Return if no phy declared */ + if (!dev_read_prop(dev, "phys", NULL)) + return 0; + count = dev_count_phandle_with_args(dev, "phys", "#phy-cells"); + if (count <= 0) + return count; + + usb_phys = devm_kcalloc(dev, count, sizeof(struct phy), + GFP_KERNEL); + if (!usb_phys) + return -ENOMEM; + + for (i = 0; i < count; i++) { + ret = generic_phy_get_by_index(dev, i, &usb_phys[i]); + if (ret && ret != -ENOENT) { + pr_err("Failed to get USB PHY%d for %s\n", + i, dev->name); + return ret; + } + } + + for (i = 0; i < count; i++) { + ret = generic_phy_init(&usb_phys[i]); + if (ret) { + pr_err("Can't init USB PHY%d for %s\n", + i, dev->name); + goto phys_init_err; + } + } + + for (i = 0; i < count; i++) { + ret = generic_phy_power_on(&usb_phys[i]); + if (ret) { + pr_err("Can't power USB PHY%d for %s\n", + i, dev->name); + goto phys_poweron_err; + } + } + + *array = usb_phys; + *num_phys = count; + return 0; + +phys_poweron_err: + for (i = count - 1; i >= 0; i--) + generic_phy_power_off(&usb_phys[i]); + for (i = 0; i < count; i++) + generic_phy_exit(&usb_phys[i]); + + return ret; + +phys_init_err: + for (; i >= 0; i--) + generic_phy_exit(&usb_phys[i]); + + return ret; +} + +int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys) +{ + int i, ret; + + for (i = 0; i < num_phys; i++) { + if (!generic_phy_valid(&usb_phys[i])) + continue; + + ret = generic_phy_power_off(&usb_phys[i]); + ret |= generic_phy_exit(&usb_phys[i]); + if (ret) { + pr_err("Can't shutdown USB PHY%d for %s\n", + i, dev->name); + } + } + + return 0; +} +#endif + +#if CONFIG_IS_ENABLED(DM_USB_GADGET) int dwc3_init(struct dwc3 *dwc) { int ret; @@ -841,5 +925,4 @@ void dwc3_remove(struct dwc3 *dwc) dwc3_core_exit(dwc); kfree(dwc->mem); } - #endif diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 56c9fd657f..bc6bba198e 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -8,72 +8,89 @@ */ #include <common.h> +#include <asm-generic/io.h> #include <dm.h> #include <dm/device-internal.h> #include <dm/lists.h> -#include <linux/usb/otg.h> -#include <linux/compat.h> +#include <dwc3-uboot.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> #include <malloc.h> #include <usb.h> #include "core.h" #include "gadget.h" -#include "linux-compat.h" +#include <reset.h> +#include <clk.h> -DECLARE_GLOBAL_DATA_PTR; +#if CONFIG_IS_ENABLED(DM_USB_GADGET) +struct dwc3_generic_peripheral { + struct dwc3 dwc3; + struct phy *phys; + int num_phys; + fdt_addr_t base; +}; -int usb_gadget_handle_interrupts(int index) +int dm_usb_gadget_handle_interrupts(struct udevice *dev) { - struct dwc3 *priv; - struct udevice *dev; - int ret; - - ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev); - if (!dev || ret) { - pr_err("No USB device found\n"); - return -ENODEV; - } - - priv = dev_get_priv(dev); + struct dwc3_generic_peripheral *priv = dev_get_priv(dev); + struct dwc3 *dwc3 = &priv->dwc3; - dwc3_gadget_uboot_handle_interrupt(priv); + dwc3_gadget_uboot_handle_interrupt(dwc3); return 0; } static int dwc3_generic_peripheral_probe(struct udevice *dev) { - struct dwc3 *priv = dev_get_priv(dev); + int rc; + struct dwc3_generic_peripheral *priv = dev_get_priv(dev); + struct dwc3 *dwc3 = &priv->dwc3; - return dwc3_init(priv); + rc = dwc3_setup_phy(dev, &priv->phys, &priv->num_phys); + if (rc) + return rc; + + dwc3->regs = map_physmem(priv->base, DWC3_OTG_REGS_END, MAP_NOCACHE); + dwc3->regs += DWC3_GLOBALS_REGS_START; + dwc3->dev = dev; + + rc = dwc3_init(dwc3); + if (rc) { + unmap_physmem(dwc3->regs, MAP_NOCACHE); + return rc; + } + + return 0; } static int dwc3_generic_peripheral_remove(struct udevice *dev) { - struct dwc3 *priv = dev_get_priv(dev); + struct dwc3_generic_peripheral *priv = dev_get_priv(dev); + struct dwc3 *dwc3 = &priv->dwc3; - dwc3_remove(priv); + dwc3_remove(dwc3); + dwc3_shutdown_phy(dev, priv->phys, priv->num_phys); + unmap_physmem(dwc3->regs, MAP_NOCACHE); return 0; } static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev) { - struct dwc3 *priv = dev_get_priv(dev); + struct dwc3_generic_peripheral *priv = dev_get_priv(dev); + struct dwc3 *dwc3 = &priv->dwc3; int node = dev_of_offset(dev); - priv->regs = (void *)devfdt_get_addr(dev); - priv->regs += DWC3_GLOBALS_REGS_START; + priv->base = devfdt_get_addr(dev); - priv->maximum_speed = usb_get_maximum_speed(node); - if (priv->maximum_speed == USB_SPEED_UNKNOWN) { + dwc3->maximum_speed = usb_get_maximum_speed(node); + if (dwc3->maximum_speed == USB_SPEED_UNKNOWN) { pr_err("Invalid usb maximum speed\n"); return -ENODEV; } - priv->dr_mode = usb_get_dr_mode(node); - if (priv->dr_mode == USB_DR_MODE_UNKNOWN) { + dwc3->dr_mode = usb_get_dr_mode(node); + if (dwc3->dr_mode == USB_DR_MODE_UNKNOWN) { pr_err("Invalid usb mode setup\n"); return -ENODEV; } @@ -81,24 +98,112 @@ static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev) return 0; } -static int dwc3_generic_peripheral_bind(struct udevice *dev) -{ - return device_probe(dev); -} - U_BOOT_DRIVER(dwc3_generic_peripheral) = { .name = "dwc3-generic-peripheral", - .id = UCLASS_USB_DEV_GENERIC, + .id = UCLASS_USB_GADGET_GENERIC, .ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata, .probe = dwc3_generic_peripheral_probe, .remove = dwc3_generic_peripheral_remove, - .bind = dwc3_generic_peripheral_bind, - .platdata_auto_alloc_size = sizeof(struct usb_platdata), - .priv_auto_alloc_size = sizeof(struct dwc3), - .flags = DM_FLAG_ALLOC_PRIV_DMA, + .priv_auto_alloc_size = sizeof(struct dwc3_generic_peripheral), +}; +#endif + +struct dwc3_glue_data { + struct clk_bulk clks; + struct reset_ctl_bulk resets; + fdt_addr_t regs; }; -static int dwc3_generic_bind(struct udevice *parent) +struct dwc3_glue_ops { + void (*select_dr_mode)(struct udevice *dev, int index, + enum usb_dr_mode mode); +}; + +void dwc3_ti_select_dr_mode(struct udevice *dev, int index, + enum usb_dr_mode mode) +{ +#define USBOTGSS_UTMI_OTG_STATUS 0x0084 +#define USBOTGSS_UTMI_OTG_OFFSET 0x0480 + +/* UTMI_OTG_STATUS REGISTER */ +#define USBOTGSS_UTMI_OTG_STATUS_SW_MODE BIT(31) +#define USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT BIT(9) +#define USBOTGSS_UTMI_OTG_STATUS_TXBITSTUFFENABLE BIT(8) +#define USBOTGSS_UTMI_OTG_STATUS_IDDIG BIT(4) +#define USBOTGSS_UTMI_OTG_STATUS_SESSEND BIT(3) +#define USBOTGSS_UTMI_OTG_STATUS_SESSVALID BIT(2) +#define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID BIT(1) +enum dwc3_omap_utmi_mode { + DWC3_OMAP_UTMI_MODE_UNKNOWN = 0, + DWC3_OMAP_UTMI_MODE_HW, + DWC3_OMAP_UTMI_MODE_SW, +}; + + u32 use_id_pin; + u32 host_mode; + u32 reg; + u32 utmi_mode; + u32 utmi_status_offset = USBOTGSS_UTMI_OTG_STATUS; + + struct dwc3_glue_data *glue = dev_get_platdata(dev); + void *base = map_physmem(glue->regs, 0x10000, MAP_NOCACHE); + + if (device_is_compatible(dev, "ti,am437x-dwc3")) + utmi_status_offset += USBOTGSS_UTMI_OTG_OFFSET; + + utmi_mode = dev_read_u32_default(dev, "utmi-mode", + DWC3_OMAP_UTMI_MODE_UNKNOWN); + if (utmi_mode != DWC3_OMAP_UTMI_MODE_HW) { + debug("%s: OTG is not supported. defaulting to PERIPHERAL\n", + dev->name); + mode = USB_DR_MODE_PERIPHERAL; + } + + switch (mode) { + case USB_DR_MODE_PERIPHERAL: + use_id_pin = 0; + host_mode = 0; + break; + case USB_DR_MODE_HOST: + use_id_pin = 0; + host_mode = 1; + break; + case USB_DR_MODE_OTG: + default: + use_id_pin = 1; + host_mode = 0; + break; + } + + reg = readl(base + utmi_status_offset); + + reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SW_MODE); + if (!use_id_pin) + reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + + writel(reg, base + utmi_status_offset); + + reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSEND | + USBOTGSS_UTMI_OTG_STATUS_VBUSVALID | + USBOTGSS_UTMI_OTG_STATUS_IDDIG); + + reg |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID | + USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT; + + if (!host_mode) + reg |= USBOTGSS_UTMI_OTG_STATUS_IDDIG | + USBOTGSS_UTMI_OTG_STATUS_VBUSVALID; + + writel(reg, base + utmi_status_offset); + + unmap_physmem(base, MAP_NOCACHE); +} + +struct dwc3_glue_ops ti_ops = { + .select_dr_mode = dwc3_ti_select_dr_mode, +}; + +static int dwc3_glue_bind(struct udevice *parent) { const void *fdt = gd->fdt_blob; int node; @@ -109,29 +214,32 @@ static int dwc3_generic_bind(struct udevice *parent) const char *name = fdt_get_name(fdt, node, NULL); enum usb_dr_mode dr_mode; struct udevice *dev; - const char *driver; + const char *driver = NULL; debug("%s: subnode name: %s\n", __func__, name); - if (strncmp(name, "dwc3@", 4)) - continue; dr_mode = usb_get_dr_mode(node); switch (dr_mode) { case USB_DR_MODE_PERIPHERAL: case USB_DR_MODE_OTG: +#if CONFIG_IS_ENABLED(DM_USB_GADGET) debug("%s: dr_mode: OTG or Peripheral\n", __func__); driver = "dwc3-generic-peripheral"; +#endif break; case USB_DR_MODE_HOST: debug("%s: dr_mode: HOST\n", __func__); - driver = "dwc3-generic-host"; + driver = "xhci-dwc3"; break; default: debug("%s: unsupported dr_mode\n", __func__); return -ENODEV; }; + if (!driver) + continue; + ret = device_bind_driver_to_node(parent, driver, name, offset_to_ofnode(node), &dev); if (ret) { @@ -144,14 +252,107 @@ static int dwc3_generic_bind(struct udevice *parent) return 0; } -static const struct udevice_id dwc3_generic_ids[] = { +static int dwc3_glue_reset_init(struct udevice *dev, + struct dwc3_glue_data *glue) +{ + int ret; + + ret = reset_get_bulk(dev, &glue->resets); + if (ret == -ENOTSUPP) + return 0; + else if (ret) + return ret; + + ret = reset_deassert_bulk(&glue->resets); + if (ret) { + reset_release_bulk(&glue->resets); + return ret; + } + + return 0; +} + +static int dwc3_glue_clk_init(struct udevice *dev, + struct dwc3_glue_data *glue) +{ + int ret; + + ret = clk_get_bulk(dev, &glue->clks); + if (ret == -ENOSYS) + return 0; + if (ret) + return ret; + +#if CONFIG_IS_ENABLED(CLK) + ret = clk_enable_bulk(&glue->clks); + if (ret) { + clk_release_bulk(&glue->clks); + return ret; + } +#endif + + return 0; +} + +static int dwc3_glue_probe(struct udevice *dev) +{ + struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev); + struct dwc3_glue_data *glue = dev_get_platdata(dev); + struct udevice *child = NULL; + int index = 0; + int ret; + + glue->regs = dev_read_addr(dev); + + ret = dwc3_glue_clk_init(dev, glue); + if (ret) + return ret; + + ret = dwc3_glue_reset_init(dev, glue); + if (ret) + return ret; + + ret = device_find_first_child(dev, &child); + if (ret) + return ret; + + while (child) { + enum usb_dr_mode dr_mode; + + dr_mode = usb_get_dr_mode(dev_of_offset(child)); + device_find_next_child(&child); + if (ops && ops->select_dr_mode) + ops->select_dr_mode(dev, index, dr_mode); + index++; + } + + return 0; +} + +static int dwc3_glue_remove(struct udevice *dev) +{ + struct dwc3_glue_data *glue = dev_get_platdata(dev); + + reset_release_bulk(&glue->resets); + + clk_release_bulk(&glue->clks); + + return dm_scan_fdt_dev(dev); +} + +static const struct udevice_id dwc3_glue_ids[] = { { .compatible = "xlnx,zynqmp-dwc3" }, + { .compatible = "ti,dwc3", .data = (ulong)&ti_ops }, { } }; U_BOOT_DRIVER(dwc3_generic_wrapper) = { .name = "dwc3-generic-wrapper", .id = UCLASS_MISC, - .of_match = dwc3_generic_ids, - .bind = dwc3_generic_bind, + .of_match = dwc3_glue_ids, + .bind = dwc3_glue_bind, + .probe = dwc3_glue_probe, + .remove = dwc3_glue_remove, + .platdata_auto_alloc_size = sizeof(struct dwc3_glue_data), + }; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 4f68887b8d..818efb3e8d 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -12,7 +12,7 @@ * * commit c00552ebaf : Merge 3.18-rc7 into usb-next */ - +#include <common.h> #include <linux/kernel.h> #include <linux/list.h> diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 193583b437..3b3d9af681 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -100,9 +100,6 @@ struct eth_dev { struct usb_gadget *gadget; struct usb_request *req; /* for control responses */ struct usb_request *stat_req; /* for cdc & rndis status */ -#if CONFIG_IS_ENABLED(DM_USB) - struct udevice *usb_udev; -#endif u8 config; struct usb_ep *in_ep, *out_ep, *status_ep; @@ -2336,40 +2333,17 @@ fail: } /*-------------------------------------------------------------------------*/ - -#if CONFIG_IS_ENABLED(DM_USB) -int dm_usb_init(struct eth_dev *e_dev) -{ - struct udevice *dev = NULL; - int ret; - - ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev); - if (!dev || ret) { - pr_err("No USB device found\n"); - return -ENODEV; - } - - e_dev->usb_udev = dev; - - return ret; -} -#endif - static int _usb_eth_init(struct ether_priv *priv) { struct eth_dev *dev = &priv->ethdev; struct usb_gadget *gadget; unsigned long ts; + int ret; unsigned long timeout = USB_CONNECT_TIMEOUT; -#if CONFIG_IS_ENABLED(DM_USB) - if (dm_usb_init(dev)) { - pr_err("USB ether not found\n"); - return -ENODEV; - } -#else - board_usb_init(0, USB_INIT_DEVICE); -#endif + ret = usb_gadget_initialize(0); + if (ret) + return ret; /* Configure default mac-addresses for the USB ethernet device */ #ifdef CONFIG_USBNET_DEV_ADDR @@ -2541,9 +2515,7 @@ void _usb_eth_halt(struct ether_priv *priv) } usb_gadget_unregister_driver(&priv->eth_driver); -#if !CONFIG_IS_ENABLED(DM_USB) - board_usb_cleanup(0, USB_INIT_DEVICE); -#endif + usb_gadget_release(0); } #ifndef CONFIG_DM_ETH @@ -2699,7 +2671,7 @@ int usb_ether_init(void) struct udevice *usb_dev; int ret; - ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &usb_dev); + ret = uclass_first_device(UCLASS_USB_GADGET_GENERIC, &usb_dev); if (!usb_dev || ret) { pr_err("No USB device found\n"); return ret; diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile index 449339f2c4..38ac2dd475 100644 --- a/drivers/usb/gadget/udc/Makefile +++ b/drivers/usb/gadget/udc/Makefile @@ -2,4 +2,8 @@ # # USB peripheral controller drivers +ifndef CONFIG_$(SPL_)DM_USB_GADGET obj-$(CONFIG_USB_DWC3_GADGET) += udc-core.o +endif + +obj-$(CONFIG_$(SPL_)DM_USB_GADGET) += udc-uclass.o udc-core.o diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index f5c30dd750..62b47781dd 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -18,7 +18,8 @@ #include <asm/cache.h> #include <asm/dma-mapping.h> #include <common.h> - +#include <dm.h> +#include <dm/device-internal.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> diff --git a/drivers/usb/gadget/udc/udc-uclass.c b/drivers/usb/gadget/udc/udc-uclass.c new file mode 100644 index 0000000000..062051857a --- /dev/null +++ b/drivers/usb/gadget/udc/udc-uclass.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + * Written by Jean-Jacques Hiblot <jjhiblot@ti.com> + */ + +#include <common.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <linux/usb/gadget.h> + +#define MAX_UDC_DEVICES 4 +static struct udevice *dev_array[MAX_UDC_DEVICES]; +int usb_gadget_initialize(int index) +{ + int ret; + struct udevice *dev = NULL; + + if (index < 0 || index >= ARRAY_SIZE(dev_array)) + return -EINVAL; + if (dev_array[index]) + return 0; + ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, index, &dev); + if (!dev || ret) { + pr_err("No USB device found\n"); + return -ENODEV; + } + dev_array[index] = dev; + return 0; +} + +int usb_gadget_release(int index) +{ +#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE) + int ret; + if (index < 0 || index >= ARRAY_SIZE(dev_array)) + return -EINVAL; + + ret = device_remove(dev_array[index], DM_REMOVE_NORMAL); + if (!ret) + dev_array[index] = NULL; + return ret; +#else + return -ENOTSUPP; +#endif +} + +int usb_gadget_handle_interrupts(int index) +{ + if (index < 0 || index >= ARRAY_SIZE(dev_array)) + return -EINVAL; + return dm_usb_gadget_handle_interrupts(dev_array[index]); +} + +UCLASS_DRIVER(usb_gadget_generic) = { + .id = UCLASS_USB_GADGET_GENERIC, + .name = "usb_gadget_generic", +}; diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index dd0d156027..83b9f119e7 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -12,6 +12,7 @@ #include <fdtdec.h> #include <generic-phy.h> #include <usb.h> +#include <dwc3-uboot.h> #include "xhci.h" #include <asm/io.h> @@ -110,105 +111,21 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val) } #if CONFIG_IS_ENABLED(DM_USB) -static int xhci_dwc3_setup_phy(struct udevice *dev) -{ - struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); - int i, ret, count; - - /* Return if no phy declared */ - if (!dev_read_prop(dev, "phys", NULL)) - return 0; - - count = dev_count_phandle_with_args(dev, "phys", "#phy-cells"); - if (count <= 0) - return count; - - plat->usb_phys = devm_kcalloc(dev, count, sizeof(struct phy), - GFP_KERNEL); - if (!plat->usb_phys) - return -ENOMEM; - - for (i = 0; i < count; i++) { - ret = generic_phy_get_by_index(dev, i, &plat->usb_phys[i]); - if (ret && ret != -ENOENT) { - pr_err("Failed to get USB PHY%d for %s\n", - i, dev->name); - return ret; - } - - ++plat->num_phys; - } - - for (i = 0; i < plat->num_phys; i++) { - ret = generic_phy_init(&plat->usb_phys[i]); - if (ret) { - pr_err("Can't init USB PHY%d for %s\n", - i, dev->name); - goto phys_init_err; - } - } - - for (i = 0; i < plat->num_phys; i++) { - ret = generic_phy_power_on(&plat->usb_phys[i]); - if (ret) { - pr_err("Can't power USB PHY%d for %s\n", - i, dev->name); - goto phys_poweron_err; - } - } - - return 0; - -phys_poweron_err: - for (; i >= 0; i--) - generic_phy_power_off(&plat->usb_phys[i]); - - for (i = 0; i < plat->num_phys; i++) - generic_phy_exit(&plat->usb_phys[i]); - - return ret; - -phys_init_err: - for (; i >= 0; i--) - generic_phy_exit(&plat->usb_phys[i]); - - return ret; -} - -static int xhci_dwc3_shutdown_phy(struct udevice *dev) -{ - struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); - int i, ret; - - for (i = 0; i < plat->num_phys; i++) { - if (!generic_phy_valid(&plat->usb_phys[i])) - continue; - - ret = generic_phy_power_off(&plat->usb_phys[i]); - ret |= generic_phy_exit(&plat->usb_phys[i]); - if (ret) { - pr_err("Can't shutdown USB PHY%d for %s\n", - i, dev->name); - } - } - - return 0; -} - static int xhci_dwc3_probe(struct udevice *dev) { struct xhci_hcor *hcor; struct xhci_hccr *hccr; struct dwc3 *dwc3_reg; enum usb_dr_mode dr_mode; + struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); int ret; hccr = (struct xhci_hccr *)((uintptr_t)dev_read_addr(dev)); hcor = (struct xhci_hcor *)((uintptr_t)hccr + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); - ret = xhci_dwc3_setup_phy(dev); - if (ret) + ret = dwc3_setup_phy(dev, &plat->usb_phys, &plat->num_phys); + if (ret && (ret != -ENOTSUPP)) return ret; dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET); @@ -227,7 +144,9 @@ static int xhci_dwc3_probe(struct udevice *dev) static int xhci_dwc3_remove(struct udevice *dev) { - xhci_dwc3_shutdown_phy(dev); + struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); + + dwc3_shutdown_phy(dev, plat->usb_phys, plat->num_phys); return xhci_deregister(dev); } diff --git a/drivers/usb/musb-new/omap2430.c b/drivers/usb/musb-new/omap2430.c index 58aed72b7d..32743aa72c 100644 --- a/drivers/usb/musb-new/omap2430.c +++ b/drivers/usb/musb-new/omap2430.c @@ -263,7 +263,7 @@ U_BOOT_DRIVER(omap2430_musb) = { #ifdef CONFIG_USB_MUSB_HOST .id = UCLASS_USB, #else - .id = UCLASS_USB_DEV_GENERIC, + .id = UCLASS_USB_GADGET_GENERIC, #endif .of_match = omap2430_musb_ids, .ofdata_to_platdata = omap2430_musb_ofdata_to_platdata, diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 6cf9826cda..d7170a3078 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -535,7 +535,7 @@ U_BOOT_DRIVER(usb_musb) = { #ifdef CONFIG_USB_MUSB_HOST .id = UCLASS_USB, #else - .id = UCLASS_USB_DEV_GENERIC, + .id = UCLASS_USB_GADGET_GENERIC, #endif .of_match = sunxi_musb_ids, .probe = musb_usb_probe, diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 037af0460c..5d4e207fd1 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -94,6 +94,7 @@ enum uclass_id { UCLASS_USB, /* USB bus */ UCLASS_USB_DEV_GENERIC, /* USB generic device */ UCLASS_USB_HUB, /* USB hub */ + UCLASS_USB_GADGET_GENERIC, /* USB generic device */ UCLASS_VIDEO, /* Video or LCD device */ UCLASS_VIDEO_BRIDGE, /* Video bridge, e.g. DisplayPort to LVDS */ UCLASS_VIDEO_CONSOLE, /* Text console driver for video device */ diff --git a/include/dwc3-uboot.h b/include/dwc3-uboot.h index 228ab3b102..9941cc37a3 100644 --- a/include/dwc3-uboot.h +++ b/include/dwc3-uboot.h @@ -38,4 +38,23 @@ struct dwc3_device { int dwc3_uboot_init(struct dwc3_device *dev); void dwc3_uboot_exit(int index); void dwc3_uboot_handle_interrupt(int index); + +struct phy; +#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB) +int dwc3_setup_phy(struct udevice *dev, struct phy **array, int *num_phys); +int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys); +#else +static inline int dwc3_setup_phy(struct udevice *dev, struct phy **array, + int *num_phys) +{ + return -ENOTSUPP; +} + +static inline int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, + int num_phys) +{ + return -ENOTSUPP; +} +#endif + #endif /* __DWC3_UBOOT_H_ */ diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index b824f13477..497798a32a 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -19,6 +19,7 @@ #define __LINUX_USB_GADGET_H #include <errno.h> +#include <usb.h> #include <linux/compat.h> #include <linux/list.h> @@ -926,4 +927,21 @@ extern void usb_ep_autoconfig_reset(struct usb_gadget *); extern int usb_gadget_handle_interrupts(int index); +#if CONFIG_IS_ENABLED(DM_USB_GADGET) +int usb_gadget_initialize(int index); +int usb_gadget_release(int index); +int dm_usb_gadget_handle_interrupts(struct udevice *dev); +#else +#include <usb.h> +static inline int usb_gadget_initialize(int index) +{ + return board_usb_init(index, USB_INIT_DEVICE); +} + +static inline int usb_gadget_release(int index) +{ + return board_usb_cleanup(index, USB_INIT_DEVICE); +} +#endif + #endif /* __LINUX_USB_GADGET_H */ diff --git a/include/syscon.h b/include/syscon.h index 2aa73e520a..3df96e3276 100644 --- a/include/syscon.h +++ b/include/syscon.h @@ -74,6 +74,19 @@ int syscon_get_by_driver_data(ulong driver_data, struct udevice **devp); struct regmap *syscon_get_regmap_by_driver_data(ulong driver_data); /** + * syscon_regmap_lookup_by_phandle() - Look up a controller by a phandle + * + * This operates by looking up the given name in the device (device + * tree property) of the device using the system controller. + * + * @dev: Device using the system controller + * @name: Name of property referring to the system controller + * @return A pointer to the regmap if found, ERR_PTR(-ve) on error + */ +struct regmap *syscon_regmap_lookup_by_phandle(struct udevice *dev, + const char *name); + +/** * syscon_get_first_range() - get the first memory range from a syscon regmap * * @driver_data: Driver data value to look up diff --git a/test/dm/syscon.c b/test/dm/syscon.c index 77c79285d9..a294dda02e 100644 --- a/test/dm/syscon.c +++ b/test/dm/syscon.c @@ -6,6 +6,7 @@ #include <common.h> #include <dm.h> #include <syscon.h> +#include <regmap.h> #include <asm/test.h> #include <dm/test.h> #include <test/ut.h> @@ -43,3 +44,31 @@ static int dm_test_syscon_by_driver_data(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_syscon_by_driver_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test system controller by phandle */ +static int dm_test_syscon_by_phandle(struct unit_test_state *uts) +{ + struct udevice *dev; + struct regmap *map; + + ut_assertok(uclass_get_device_by_name(UCLASS_TEST_PROBE, "test4", + &dev)); + + ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev, "first-syscon")); + map = syscon_regmap_lookup_by_phandle(dev, "first-syscon"); + ut_assert(map); + ut_assert(!IS_ERR(map)); + ut_asserteq(1, map->range_count); + + ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev, + "second-sys-ctrl")); + map = syscon_regmap_lookup_by_phandle(dev, "second-sys-ctrl"); + ut_assert(map); + ut_assert(!IS_ERR(map)); + ut_asserteq(4, map->range_count); + + ut_assert(IS_ERR(syscon_regmap_lookup_by_phandle(dev, "not-present"))); + + return 0; +} +DM_TEST(dm_test_syscon_by_phandle, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); |