Skip to content

Commit

Permalink
dwc3: move phy operation to core.c
Browse files Browse the repository at this point in the history
Those operations can be used for peripheral operation as well as host
operation.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>

# Conflicts:
#	drivers/usb/dwc3/core.c
#	drivers/usb/host/xhci-dwc3.c
  • Loading branch information
Jean-Jacques Hiblot authored and Marek Vasut committed Dec 7, 2018
1 parent 20bebd8 commit d648a50
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 90 deletions.
88 changes: 86 additions & 2 deletions drivers/usb/dwc3/core.c
Expand Up @@ -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>

Expand Down Expand Up @@ -789,6 +789,91 @@ MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");

#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)
{
Expand Down Expand Up @@ -840,5 +925,4 @@ void dwc3_remove(struct dwc3 *dwc)
dwc3_core_exit(dwc);
kfree(dwc->mem);
}

#endif
95 changes: 7 additions & 88 deletions drivers/usb/host/xhci-dwc3.c
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
Expand Down
19 changes: 19 additions & 0 deletions include/dwc3-uboot.h
Expand Up @@ -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_ */

0 comments on commit d648a50

Please sign in to comment.