mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-17 12:41:32 +00:00
Merge branch 'master' of git://git.denx.de/u-boot-usb
- DWC3 and UDC cleanup
This commit is contained in:
commit
48d299a799
39 changed files with 857 additions and 407 deletions
|
@ -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"
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
196
drivers/phy/omap-usb2-phy.c
Normal 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),
|
||||
};
|
|
@ -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},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* commit c00552ebaf : Merge 3.18-rc7 into usb-next
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
58
drivers/usb/gadget/udc/udc-uclass.c
Normal file
58
drivers/usb/gadget/udc/udc-uclass.c
Normal 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",
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue