Merge branch 'master' of git://git.denx.de/u-boot-usb

- DWC3 and UDC cleanup
This commit is contained in:
Tom Rini 2018-12-10 07:15:12 -05:00
commit 48d299a799
39 changed files with 857 additions and 407 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -675,6 +675,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();
@ -714,6 +727,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;
}
@ -864,93 +883,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 */

View file

@ -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
@ -684,6 +697,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)
{

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -50,6 +50,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
@ -61,6 +62,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
@ -70,13 +74,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"

View file

@ -53,6 +53,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
@ -64,6 +65,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
@ -73,13 +77,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"

View file

@ -56,6 +56,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"

View file

@ -56,6 +56,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
@ -71,6 +72,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
@ -86,14 +88,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"

View file

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

View file

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

View file

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

View file

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

196
drivers/phy/omap-usb2-phy.c Normal file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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;
struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
struct dwc3 *dwc3 = &priv->dwc3;
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);
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),
};

View file

@ -12,7 +12,7 @@
*
* commit c00552ebaf : Merge 3.18-rc7 into usb-next
*/
#include <common.h>
#include <linux/kernel.h>
#include <linux/list.h>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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_ */

View file

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

View file

@ -73,6 +73,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
*

View file

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