summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2019-04-22 02:00:04 +0300
committerTom Rini <trini@konsulko.com>2019-04-22 02:00:04 +0300
commit6c5f8dd540d7a8eff244d4c27a09451ca12c8d20 (patch)
tree9eaba554d99f15aa5dfc302c338f59895f9b43e4 /drivers
parentb4fde1633e67bb618fd33aad6e6322b7cecf1154 (diff)
parent7fd9f31c6bd13609da61b985cf8f5f65ebebd913 (diff)
downloadu-boot-6c5f8dd540d7a8eff244d4c27a09451ca12c8d20.tar.xz
Merge branch 'master' of git://git.denx.de/u-boot-usb
- Various fastboot, dwc2/stm32 updates
Diffstat (limited to 'drivers')
-rw-r--r--drivers/fastboot/fb_getvar.c16
-rw-r--r--drivers/fastboot/fb_mmc.c10
-rw-r--r--drivers/phy/phy-stm32-usbphyc.c111
-rw-r--r--drivers/usb/gadget/dwc2_udc_otg.c388
-rw-r--r--drivers/usb/gadget/dwc2_udc_otg_priv.h1
-rw-r--r--drivers/usb/gadget/dwc2_udc_otg_regs.h37
-rw-r--r--drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c14
-rw-r--r--drivers/usb/musb-new/Kconfig10
8 files changed, 509 insertions, 78 deletions
diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c
index 4d264c985d..4268628f5e 100644
--- a/drivers/fastboot/fb_getvar.c
+++ b/drivers/fastboot/fb_getvar.c
@@ -17,6 +17,7 @@ static void getvar_downloadsize(char *var_parameter, char *response);
static void getvar_serialno(char *var_parameter, char *response);
static void getvar_version_baseband(char *var_parameter, char *response);
static void getvar_product(char *var_parameter, char *response);
+static void getvar_platform(char *var_parameter, char *response);
static void getvar_current_slot(char *var_parameter, char *response);
static void getvar_slot_suffixes(char *var_parameter, char *response);
static void getvar_has_slot(char *var_parameter, char *response);
@@ -56,13 +57,16 @@ static const struct {
.variable = "product",
.dispatch = getvar_product
}, {
+ .variable = "platform",
+ .dispatch = getvar_platform
+ }, {
.variable = "current-slot",
.dispatch = getvar_current_slot
}, {
.variable = "slot-suffixes",
.dispatch = getvar_slot_suffixes
}, {
- .variable = "has_slot",
+ .variable = "has-slot",
.dispatch = getvar_has_slot
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
}, {
@@ -117,6 +121,16 @@ static void getvar_product(char *var_parameter, char *response)
fastboot_fail("Board not set", response);
}
+static void getvar_platform(char *var_parameter, char *response)
+{
+ const char *p = env_get("platform");
+
+ if (p)
+ fastboot_okay(p, response);
+ else
+ fastboot_fail("platform not set", response);
+}
+
static void getvar_current_slot(char *var_parameter, char *response)
{
/* A/B not implemented, for now always return _a */
diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c
index 4c1c7fd2cd..90ca81da9b 100644
--- a/drivers/fastboot/fb_mmc.c
+++ b/drivers/fastboot/fb_mmc.c
@@ -31,13 +31,13 @@ static int part_get_info_by_name_or_alias(struct blk_desc *dev_desc,
ret = part_get_info_by_name(dev_desc, name, info);
if (ret < 0) {
- /* strlen("fastboot_partition_alias_") + 32(part_name) + 1 */
- char env_alias_name[25 + 32 + 1];
+ /* strlen("fastboot_partition_alias_") + PART_NAME_LEN + 1 */
+ char env_alias_name[25 + PART_NAME_LEN + 1];
char *aliased_part_name;
/* check for alias */
strcpy(env_alias_name, "fastboot_partition_alias_");
- strncat(env_alias_name, name, 32);
+ strncat(env_alias_name, name, PART_NAME_LEN);
aliased_part_name = env_get(env_alias_name);
if (aliased_part_name != NULL)
ret = part_get_info_by_name(dev_desc,
@@ -308,8 +308,8 @@ int fastboot_mmc_get_part_info(char *part_name, struct blk_desc **dev_desc,
fastboot_fail("block device not found", response);
return -ENOENT;
}
- if (!part_name) {
- fastboot_fail("partition not found", response);
+ if (!part_name || !strcmp(part_name, "")) {
+ fastboot_fail("partition not given", response);
return -ENOENT;
}
diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c
index 8e98b4b627..6f1119036d 100644
--- a/drivers/phy/phy-stm32-usbphyc.c
+++ b/drivers/phy/phy-stm32-usbphyc.c
@@ -37,7 +37,8 @@
#define MAX_PHYS 2
-#define PLL_LOCK_TIME_US 100
+/* max 100 us for PLL lock and 100 us for PHY init */
+#define PLL_INIT_TIME_US 200
#define PLL_PWR_DOWN_TIME_US 5
#define PLL_FVCO 2880 /* in MHz */
#define PLL_INFF_MIN_RATE 19200000 /* in Hz */
@@ -51,17 +52,17 @@ struct pll_params {
struct stm32_usbphyc {
fdt_addr_t base;
struct clk clk;
+ struct udevice *vdda1v1;
+ struct udevice *vdda1v8;
struct stm32_usbphyc_phy {
struct udevice *vdd;
- struct udevice *vdda1v1;
- struct udevice *vdda1v8;
- int index;
bool init;
bool powered;
} phys[MAX_PHYS];
};
-void stm32_usbphyc_get_pll_params(u32 clk_rate, struct pll_params *pll_params)
+static void stm32_usbphyc_get_pll_params(u32 clk_rate,
+ struct pll_params *pll_params)
{
unsigned long long fvco, ndiv, frac;
@@ -154,6 +155,18 @@ static int stm32_usbphyc_phy_init(struct phy *phy)
if (pllen && stm32_usbphyc_is_init(usbphyc))
goto initialized;
+ if (usbphyc->vdda1v1) {
+ ret = regulator_set_enable(usbphyc->vdda1v1, true);
+ if (ret)
+ return ret;
+ }
+
+ if (usbphyc->vdda1v8) {
+ ret = regulator_set_enable(usbphyc->vdda1v8, true);
+ if (ret)
+ return ret;
+ }
+
if (pllen) {
clrbits_le32(usbphyc->base + STM32_USBPHYC_PLL, PLLEN);
udelay(PLL_PWR_DOWN_TIME_US);
@@ -165,11 +178,8 @@ static int stm32_usbphyc_phy_init(struct phy *phy)
setbits_le32(usbphyc->base + STM32_USBPHYC_PLL, PLLEN);
- /*
- * We must wait PLL_LOCK_TIME_US before checking that PLLEN
- * bit is still set
- */
- udelay(PLL_LOCK_TIME_US);
+ /* We must wait PLL_INIT_TIME_US before using PHY */
+ udelay(PLL_INIT_TIME_US);
if (!(readl(usbphyc->base + STM32_USBPHYC_PLL) & PLLEN))
return -EIO;
@@ -184,6 +194,7 @@ static int stm32_usbphyc_phy_exit(struct phy *phy)
{
struct stm32_usbphyc *usbphyc = dev_get_priv(phy->dev);
struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + phy->id;
+ int ret;
pr_debug("%s phy ID = %lu\n", __func__, phy->id);
usbphyc_phy->init = false;
@@ -203,6 +214,18 @@ static int stm32_usbphyc_phy_exit(struct phy *phy)
if (readl(usbphyc->base + STM32_USBPHYC_PLL) & PLLEN)
return -EIO;
+ if (usbphyc->vdda1v1) {
+ ret = regulator_set_enable(usbphyc->vdda1v1, false);
+ if (ret)
+ return ret;
+ }
+
+ if (usbphyc->vdda1v8) {
+ ret = regulator_set_enable(usbphyc->vdda1v8, false);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
@@ -213,17 +236,6 @@ static int stm32_usbphyc_phy_power_on(struct phy *phy)
int ret;
pr_debug("%s phy ID = %lu\n", __func__, phy->id);
- if (usbphyc_phy->vdda1v1) {
- ret = regulator_set_enable(usbphyc_phy->vdda1v1, true);
- if (ret)
- return ret;
- }
-
- if (usbphyc_phy->vdda1v8) {
- ret = regulator_set_enable(usbphyc_phy->vdda1v8, true);
- if (ret)
- return ret;
- }
if (usbphyc_phy->vdd) {
ret = regulator_set_enable(usbphyc_phy->vdd, true);
if (ret)
@@ -247,18 +259,6 @@ static int stm32_usbphyc_phy_power_off(struct phy *phy)
if (stm32_usbphyc_is_powered(usbphyc))
return 0;
- if (usbphyc_phy->vdda1v1) {
- ret = regulator_set_enable(usbphyc_phy->vdda1v1, false);
- if (ret)
- return ret;
- }
-
- if (usbphyc_phy->vdda1v8) {
- ret = regulator_set_enable(usbphyc_phy->vdda1v8, false);
- if (ret)
- return ret;
- }
-
if (usbphyc_phy->vdd) {
ret = regulator_set_enable(usbphyc_phy->vdd, false);
if (ret)
@@ -298,19 +298,20 @@ static int stm32_usbphyc_get_regulator(struct udevice *dev, ofnode node,
static int stm32_usbphyc_of_xlate(struct phy *phy,
struct ofnode_phandle_args *args)
{
- if (args->args_count > 1) {
- pr_debug("%s: invalid args_count: %d\n", __func__,
- args->args_count);
- return -EINVAL;
- }
+ if (args->args_count < 1)
+ return -ENODEV;
if (args->args[0] >= MAX_PHYS)
return -ENODEV;
- if (args->args_count)
- phy->id = args->args[0];
- else
- phy->id = 0;
+ phy->id = args->args[0];
+
+ if ((phy->id == 0 && args->args_count != 1) ||
+ (phy->id == 1 && args->args_count != 2)) {
+ dev_err(dev, "invalid number of cells for phy port%ld\n",
+ phy->id);
+ return -EINVAL;
+ }
return 0;
}
@@ -351,6 +352,21 @@ static int stm32_usbphyc_probe(struct udevice *dev)
reset_deassert(&reset);
}
+ /* get usbphyc regulator */
+ ret = device_get_supply_regulator(dev, "vdda1v1-supply",
+ &usbphyc->vdda1v1);
+ if (ret) {
+ dev_err(dev, "Can't get vdda1v1-supply regulator\n");
+ return ret;
+ }
+
+ ret = device_get_supply_regulator(dev, "vdda1v8-supply",
+ &usbphyc->vdda1v8);
+ if (ret) {
+ dev_err(dev, "Can't get vdda1v8-supply regulator\n");
+ return ret;
+ }
+
/*
* parse all PHY subnodes in order to populate regulator associated
* to each PHY port
@@ -359,7 +375,6 @@ static int stm32_usbphyc_probe(struct udevice *dev)
for (i = 0; i < MAX_PHYS; i++) {
struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + i;
- usbphyc_phy->index = i;
usbphyc_phy->init = false;
usbphyc_phy->powered = false;
ret = stm32_usbphyc_get_regulator(dev, node, "phy-supply",
@@ -367,16 +382,6 @@ static int stm32_usbphyc_probe(struct udevice *dev)
if (ret)
return ret;
- ret = stm32_usbphyc_get_regulator(dev, node, "vdda1v1-supply",
- &usbphyc_phy->vdda1v1);
- if (ret)
- return ret;
-
- ret = stm32_usbphyc_get_regulator(dev, node, "vdda1v8-supply",
- &usbphyc_phy->vdda1v8);
- if (ret)
- return ret;
-
node = dev_read_next_subnode(node);
}
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index 3c7ad033e3..494ab533cc 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -18,11 +18,17 @@
*/
#undef DEBUG
#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <malloc.h>
+#include <reset.h>
+
#include <linux/errno.h>
#include <linux/list.h>
-#include <malloc.h>
#include <linux/usb/ch9.h>
+#include <linux/usb/otg.h>
#include <linux/usb/gadget.h>
#include <asm/byteorder.h>
@@ -31,6 +37,8 @@
#include <asm/mach-types.h>
+#include <power/regulator.h>
+
#include "dwc2_udc_otg_regs.h"
#include "dwc2_udc_otg_priv.h"
@@ -140,7 +148,6 @@ static struct usb_ep_ops dwc2_ep_ops = {
/***********************************************************/
-void __iomem *regs_otg;
struct dwc2_usbotg_reg *reg;
bool dfu_usb_get_reset(void)
@@ -223,6 +230,7 @@ static int udc_enable(struct dwc2_udc *dev)
return 0;
}
+#if !CONFIG_IS_ENABLED(DM_USB_GADGET)
/*
Register entry point for the peripheral controller driver.
*/
@@ -297,6 +305,54 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
udc_disable(dev);
return 0;
}
+#else /* !CONFIG_IS_ENABLED(DM_USB_GADGET) */
+
+static int dwc2_gadget_start(struct usb_gadget *g,
+ struct usb_gadget_driver *driver)
+{
+ struct dwc2_udc *dev = the_controller;
+
+ debug_cond(DEBUG_SETUP != 0, "%s: %s\n", __func__, "no name");
+
+ if (!driver ||
+ (driver->speed != USB_SPEED_FULL &&
+ driver->speed != USB_SPEED_HIGH) ||
+ !driver->bind || !driver->disconnect || !driver->setup)
+ return -EINVAL;
+
+ if (!dev)
+ return -ENODEV;
+
+ if (dev->driver)
+ return -EBUSY;
+
+ /* first hook up the driver ... */
+ dev->driver = driver;
+
+ debug_cond(DEBUG_SETUP != 0,
+ "Registered gadget driver %s\n", dev->gadget.name);
+ return udc_enable(dev);
+}
+
+static int dwc2_gadget_stop(struct usb_gadget *g)
+{
+ struct dwc2_udc *dev = the_controller;
+
+ if (!dev)
+ return -ENODEV;
+
+ if (!dev->driver)
+ return -EINVAL;
+
+ dev->driver = 0;
+ stop_activity(dev, dev->driver);
+
+ udc_disable(dev);
+
+ return 0;
+}
+
+#endif /* !CONFIG_IS_ENABLED(DM_USB_GADGET) */
/*
* done - retire a request; caller blocked irqs
@@ -400,6 +456,8 @@ static void reconfig_usbd(struct dwc2_udc *dev)
unsigned int uTemp = writel(CORE_SOFT_RESET, &reg->grstctl);
uint32_t dflt_gusbcfg;
uint32_t rx_fifo_sz, tx_fifo_sz, np_tx_fifo_sz;
+ u32 max_hw_ep;
+ int pdata_hw_ep;
debug("Reseting OTG controller\n");
@@ -482,10 +540,23 @@ static void reconfig_usbd(struct dwc2_udc *dev)
writel((np_tx_fifo_sz << 16) | rx_fifo_sz,
&reg->gnptxfsiz);
- for (i = 1; i < DWC2_MAX_HW_ENDPOINTS; i++)
- writel((rx_fifo_sz + np_tx_fifo_sz + tx_fifo_sz*(i-1)) |
- tx_fifo_sz << 16, &reg->dieptxf[i-1]);
+ /* retrieve the number of IN Endpoints (excluding ep0) */
+ max_hw_ep = (readl(&reg->ghwcfg4) & GHWCFG4_NUM_IN_EPS_MASK) >>
+ GHWCFG4_NUM_IN_EPS_SHIFT;
+ pdata_hw_ep = dev->pdata->tx_fifo_sz_nb;
+
+ /* tx_fifo_sz_nb should equal to number of IN Endpoint */
+ if (pdata_hw_ep && max_hw_ep != pdata_hw_ep)
+ pr_warn("Got %d hw endpoint but %d tx-fifo-size in array !!\n",
+ max_hw_ep, pdata_hw_ep);
+
+ for (i = 0; i < max_hw_ep; i++) {
+ if (pdata_hw_ep)
+ tx_fifo_sz = dev->pdata->tx_fifo_sz_array[i];
+ writel((rx_fifo_sz + np_tx_fifo_sz + (tx_fifo_sz * i)) |
+ tx_fifo_sz << 16, &reg->dieptxf[i]);
+ }
/* Flush the RX FIFO */
writel(RX_FIFO_FLUSH, &reg->grstctl);
while (readl(&reg->grstctl) & RX_FIFO_FLUSH)
@@ -731,6 +802,10 @@ static void dwc2_fifo_flush(struct usb_ep *_ep)
static const struct usb_gadget_ops dwc2_udc_ops = {
/* current versions must always be self-powered */
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+ .udc_start = dwc2_gadget_start,
+ .udc_stop = dwc2_gadget_stop,
+#endif
};
static struct dwc2_udc memory = {
@@ -818,8 +893,6 @@ int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata)
reg = (struct dwc2_usbotg_reg *)pdata->regs_otg;
- /* regs_otg = (void *)pdata->regs_otg; */
-
dev->gadget.is_dualspeed = 1; /* Hack only*/
dev->gadget.is_otg = 0;
dev->gadget.is_a_peripheral = 0;
@@ -844,12 +917,311 @@ int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata)
return retval;
}
-int usb_gadget_handle_interrupts(int index)
+int dwc2_udc_handle_interrupt(void)
{
u32 intr_status = readl(&reg->gintsts);
u32 gintmsk = readl(&reg->gintmsk);
if (intr_status & gintmsk)
return dwc2_udc_irq(1, (void *)the_controller);
+
+ return 0;
+}
+
+#if !CONFIG_IS_ENABLED(DM_USB_GADGET)
+
+int usb_gadget_handle_interrupts(int index)
+{
+ return dwc2_udc_handle_interrupt();
+}
+
+#else /* CONFIG_IS_ENABLED(DM_USB_GADGET) */
+
+struct dwc2_priv_data {
+ struct clk_bulk clks;
+ struct reset_ctl_bulk resets;
+ struct phy *phys;
+ int num_phys;
+ struct udevice *usb33d_supply;
+};
+
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
+{
+ return dwc2_udc_handle_interrupt();
+}
+
+int dwc2_phy_setup(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) {
+ dev_err(dev, "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) {
+ dev_err(dev, "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) {
+ dev_err(dev, "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;
+}
+
+void dwc2_phy_shutdown(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) {
+ dev_err(dev, "Can't shutdown USB PHY%d for %s\n",
+ i, dev->name);
+ }
+ }
+}
+
+static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev)
+{
+ struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev);
+ int node = dev_of_offset(dev);
+ ulong drvdata;
+ void (*set_params)(struct dwc2_plat_otg_data *data);
+
+ if (usb_get_dr_mode(node) != USB_DR_MODE_PERIPHERAL) {
+ dev_dbg(dev, "Invalid mode\n");
+ return -ENODEV;
+ }
+
+ platdata->regs_otg = dev_read_addr(dev);
+
+ platdata->rx_fifo_sz = dev_read_u32_default(dev, "g-rx-fifo-size", 0);
+ platdata->np_tx_fifo_sz = dev_read_u32_default(dev,
+ "g-np-tx-fifo-size", 0);
+ platdata->tx_fifo_sz = dev_read_u32_default(dev, "g-tx-fifo-size", 0);
+
+ platdata->force_b_session_valid =
+ dev_read_bool(dev, "u-boot,force-b-session-valid");
+
+ /* force platdata according compatible */
+ drvdata = dev_get_driver_data(dev);
+ if (drvdata) {
+ set_params = (void *)drvdata;
+ set_params(platdata);
+ }
+
+ return 0;
+}
+
+static void dwc2_set_stm32mp1_hsotg_params(struct dwc2_plat_otg_data *p)
+{
+ p->activate_stm_id_vb_detection = true;
+ p->usb_gusbcfg =
+ 0 << 15 /* PHY Low Power Clock sel*/
+ | 0x9 << 10 /* USB Turnaround time (0x9 for HS phy) */
+ | 0 << 9 /* [0:HNP disable,1:HNP enable]*/
+ | 0 << 8 /* [0:SRP disable 1:SRP enable]*/
+ | 0 << 6 /* 0: high speed utmi+, 1: full speed serial*/
+ | 0x7 << 0; /* FS timeout calibration**/
+
+ if (p->force_b_session_valid)
+ p->usb_gusbcfg |= 1 << 30; /* FDMOD: Force device mode */
+}
+
+static int dwc2_udc_otg_reset_init(struct udevice *dev,
+ struct reset_ctl_bulk *resets)
+{
+ int ret;
+
+ ret = reset_get_bulk(dev, resets);
+ if (ret == -ENOTSUPP)
+ return 0;
+
+ if (ret)
+ return ret;
+
+ ret = reset_assert_bulk(resets);
+
+ if (!ret) {
+ udelay(2);
+ ret = reset_deassert_bulk(resets);
+ }
+ if (ret) {
+ reset_release_bulk(resets);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int dwc2_udc_otg_clk_init(struct udevice *dev,
+ struct clk_bulk *clks)
+{
+ int ret;
+
+ ret = clk_get_bulk(dev, clks);
+ if (ret == -ENOSYS)
+ return 0;
+
+ if (ret)
+ return ret;
+
+ ret = clk_enable_bulk(clks);
+ if (ret) {
+ clk_release_bulk(clks);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int dwc2_udc_otg_probe(struct udevice *dev)
+{
+ struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev);
+ struct dwc2_priv_data *priv = dev_get_priv(dev);
+ struct dwc2_usbotg_reg *usbotg_reg =
+ (struct dwc2_usbotg_reg *)platdata->regs_otg;
+ int ret;
+
+ ret = dwc2_udc_otg_clk_init(dev, &priv->clks);
+ if (ret)
+ return ret;
+
+ ret = dwc2_udc_otg_reset_init(dev, &priv->resets);
+ if (ret)
+ return ret;
+
+ ret = dwc2_phy_setup(dev, &priv->phys, &priv->num_phys);
+ if (ret)
+ return ret;
+
+ if (CONFIG_IS_ENABLED(DM_REGULATOR) &&
+ platdata->activate_stm_id_vb_detection &&
+ !platdata->force_b_session_valid) {
+ ret = device_get_supply_regulator(dev, "usb33d-supply",
+ &priv->usb33d_supply);
+ if (ret) {
+ dev_err(dev, "can't get voltage level detector supply\n");
+ return ret;
+ }
+ ret = regulator_set_enable(priv->usb33d_supply, true);
+ if (ret) {
+ dev_err(dev, "can't enable voltage level detector supply\n");
+ return ret;
+ }
+ /* Enable vbus sensing */
+ setbits_le32(&usbotg_reg->ggpio,
+ GGPIO_STM32_OTG_GCCFG_VBDEN |
+ GGPIO_STM32_OTG_GCCFG_IDEN);
+ }
+
+ if (platdata->force_b_session_valid)
+ /* Override B session bits : value and enable */
+ setbits_le32(&usbotg_reg->gotgctl,
+ A_VALOEN | A_VALOVAL | B_VALOEN | B_VALOVAL);
+
+ ret = dwc2_udc_probe(platdata);
+ if (ret)
+ return ret;
+
+ the_controller->driver = 0;
+
+ ret = usb_add_gadget_udc((struct device *)dev, &the_controller->gadget);
+
+ return ret;
+}
+
+static int dwc2_udc_otg_remove(struct udevice *dev)
+{
+ struct dwc2_priv_data *priv = dev_get_priv(dev);
+
+ usb_del_gadget_udc(&the_controller->gadget);
+
+ reset_release_bulk(&priv->resets);
+
+ clk_release_bulk(&priv->clks);
+
+ dwc2_phy_shutdown(dev, priv->phys, priv->num_phys);
+
+ return dm_scan_fdt_dev(dev);
+}
+
+static const struct udevice_id dwc2_udc_otg_ids[] = {
+ { .compatible = "snps,dwc2" },
+ { .compatible = "st,stm32mp1-hsotg",
+ .data = (ulong)dwc2_set_stm32mp1_hsotg_params },
+ {},
+};
+
+U_BOOT_DRIVER(dwc2_udc_otg) = {
+ .name = "dwc2-udc-otg",
+ .id = UCLASS_USB_GADGET_GENERIC,
+ .of_match = dwc2_udc_otg_ids,
+ .ofdata_to_platdata = dwc2_udc_otg_ofdata_to_platdata,
+ .probe = dwc2_udc_otg_probe,
+ .remove = dwc2_udc_otg_remove,
+ .platdata_auto_alloc_size = sizeof(struct dwc2_plat_otg_data),
+ .priv_auto_alloc_size = sizeof(struct dwc2_priv_data),
+};
+
+int dwc2_udc_B_session_valid(struct udevice *dev)
+{
+ struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev);
+ struct dwc2_usbotg_reg *usbotg_reg =
+ (struct dwc2_usbotg_reg *)platdata->regs_otg;
+
+ return readl(&usbotg_reg->gotgctl) & B_SESSION_VALID;
}
+#endif /* CONFIG_IS_ENABLED(DM_USB_GADGET) */
diff --git a/drivers/usb/gadget/dwc2_udc_otg_priv.h b/drivers/usb/gadget/dwc2_udc_otg_priv.h
index aaa90187fb..e72b22ac61 100644
--- a/drivers/usb/gadget/dwc2_udc_otg_priv.h
+++ b/drivers/usb/gadget/dwc2_udc_otg_priv.h
@@ -23,7 +23,6 @@
#define EP_FIFO_SIZE2 1024
/* ep0-control, ep1in-bulk, ep2out-bulk, ep3in-int */
#define DWC2_MAX_ENDPOINTS 4
-#define DWC2_MAX_HW_ENDPOINTS 16
#define WAIT_FOR_SETUP 0
#define DATA_STATE_XMIT 1
diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h
index a1829b3fd1..434db5ba39 100644
--- a/drivers/usb/gadget/dwc2_udc_otg_regs.h
+++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h
@@ -60,22 +60,26 @@ struct dwc2_usbotg_reg {
u32 grxstsp; /* Receive Status Debug Pop/Status Pop */
u32 grxfsiz; /* Receive FIFO Size */
u32 gnptxfsiz; /* Non-Periodic Transmit FIFO Size */
- u8 res1[216];
+ u8 res0[12];
+ u32 ggpio; /* 0x038 */
+ u8 res1[20];
+ u32 ghwcfg4; /* User HW Config4 */
+ u8 res2[176];
u32 dieptxf[15]; /* Device Periodic Transmit FIFO size register */
- u8 res2[1728];
+ u8 res3[1728];
/* Device Configuration */
u32 dcfg; /* Device Configuration Register */
u32 dctl; /* Device Control */
u32 dsts; /* Device Status */
- u8 res3[4];
+ u8 res4[4];
u32 diepmsk; /* Device IN Endpoint Common Interrupt Mask */
u32 doepmsk; /* Device OUT Endpoint Common Interrupt Mask */
u32 daint; /* Device All Endpoints Interrupt */
u32 daintmsk; /* Device All Endpoints Interrupt Mask */
- u8 res4[224];
+ u8 res5[224];
struct dwc2_dev_in_endp in_endp[16];
struct dwc2_dev_out_endp out_endp[16];
- u8 res5[768];
+ u8 res6[768];
struct ep_fifo ep[16];
};
@@ -83,8 +87,15 @@ struct dwc2_usbotg_reg {
/*definitions related to CSR setting */
/* DWC2_UDC_OTG_GOTGCTL */
-#define B_SESSION_VALID (0x1<<19)
-#define A_SESSION_VALID (0x1<<18)
+#define B_SESSION_VALID BIT(19)
+#define A_SESSION_VALID BIT(18)
+#define B_VALOVAL BIT(7)
+#define B_VALOEN BIT(6)
+#define A_VALOVAL BIT(5)
+#define A_VALOEN BIT(4)
+
+/* DWC2_UDC_OTG_GOTINT */
+#define GOTGINT_SES_END_DET (1<<2)
/* DWC2_UDC_OTG_GAHBCFG */
#define PTXFE_HALF (0<<8)
@@ -118,6 +129,7 @@ struct dwc2_usbotg_reg {
#define INT_NP_TX_FIFO_EMPTY (0x1<<5)
#define INT_RX_FIFO_NOT_EMPTY (0x1<<4)
#define INT_SOF (0x1<<3)
+#define INT_OTG (0x1<<2)
#define INT_DEV_MODE (0x0<<0)
#define INT_HOST_MODE (0x1<<1)
#define INT_GOUTNakEff (0x01<<7)
@@ -246,7 +258,7 @@ struct dwc2_usbotg_reg {
/* Masks definitions */
#define GINTMSK_INIT (INT_OUT_EP | INT_IN_EP | INT_RESUME | INT_ENUMDONE\
- | INT_RESET | INT_SUSPEND)
+ | INT_RESET | INT_SUSPEND | INT_OTG)
#define DOEPMSK_INIT (CTRL_OUT_EP_SETUP_PHASE_DONE | AHB_ERROR|TRANSFER_DONE)
#define DIEPMSK_INIT (NON_ISO_IN_EP_TIMEOUT|AHB_ERROR|TRANSFER_DONE)
#define GAHBCFG_INIT (PTXFE_HALF | NPTXFE_HALF | MODE_DMA | BURST_INCR4\
@@ -269,4 +281,13 @@ struct dwc2_usbotg_reg {
/* Device ALL Endpoints Interrupt Register (DAINT) */
#define DAINT_IN_EP_INT(x) (x << 0)
#define DAINT_OUT_EP_INT(x) (x << 16)
+
+/* User HW Config4 */
+#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26)
+#define GHWCFG4_NUM_IN_EPS_SHIFT 26
+
+/* OTG general core configuration register (OTG_GCCFG:0x38) for STM32MP1 */
+#define GGPIO_STM32_OTG_GCCFG_VBDEN BIT(21)
+#define GGPIO_STM32_OTG_GCCFG_IDEN BIT(22)
+
#endif
diff --git a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c
index a75af4987f..7eb632d3b1 100644
--- a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c
+++ b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c
@@ -467,7 +467,7 @@ static void process_ep_out_intr(struct dwc2_udc *dev)
static int dwc2_udc_irq(int irq, void *_dev)
{
struct dwc2_udc *dev = _dev;
- u32 intr_status;
+ u32 intr_status, gotgint;
u32 usb_status, gintmsk;
unsigned long flags = 0;
@@ -521,14 +521,24 @@ static int dwc2_udc_irq(int irq, void *_dev)
&& dev->driver) {
if (dev->driver->suspend)
dev->driver->suspend(&dev->gadget);
+ }
+ }
+
+ if (intr_status & INT_OTG) {
+ gotgint = readl(&reg->gotgint);
+ debug_cond(DEBUG_ISR,
+ "\tOTG interrupt: (GOTGINT):0x%x\n", gotgint);
- /* HACK to let gadget detect disconnected state */
+ if (gotgint & GOTGINT_SES_END_DET) {
+ debug_cond(DEBUG_ISR, "\t\tSession End Detected\n");
+ /* Let gadget detect disconnected state */
if (dev->driver->disconnect) {
spin_unlock_irqrestore(&dev->lock, flags);
dev->driver->disconnect(&dev->gadget);
spin_lock_irqsave(&dev->lock, flags);
}
}
+ writel(gotgint, &reg->gotgint);
}
if (intr_status & INT_RESUME) {
diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig
index f8f2205a62..75005ccdd1 100644
--- a/drivers/usb/musb-new/Kconfig
+++ b/drivers/usb/musb-new/Kconfig
@@ -21,6 +21,7 @@ config USB_MUSB_GADGET
config USB_MUSB_TI
bool "Enable TI OTG USB controller"
depends on DM_USB
+ select USB_MUSB_DSPS
default n
help
Say y here to enable support for the dual role high
@@ -54,6 +55,15 @@ config USB_MUSB_SUNXI
Say y here to enable support for the sunxi OTG / DRC USB controller
used on almost all sunxi boards.
+config USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
+ bool "Disable MUSB bulk split/combine"
+ default y
+ help
+ On TI AM335x devices, MUSB has bulk split/combine feature enabled
+ in the ConfigData register, but the current MUSB driver does not
+ support it yet. Select this option to disable the feature until the
+ driver adds the support.
+
endif
config USB_MUSB_PIO_ONLY