u-boot/drivers/usb/host/ehci-msm.c
Tom Rini d678a59d2d Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
When bringing in the series 'arm: dts: am62-beagleplay: Fix Beagleplay
Ethernet"' I failed to notice that b4 noticed it was based on next and
so took that as the base commit and merged that part of next to master.

This reverts commit c8ffd1356d, reversing
changes made to 2ee6f3a5f7.

Reported-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Tom Rini <trini@konsulko.com>
2024-05-19 08:16:36 -06:00

171 lines
3.7 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Qualcomm EHCI driver
*
* (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
*
* Based on Linux driver
*/
#include <common.h>
#include <dm.h>
#include <dm/lists.h>
#include <errno.h>
#include <usb.h>
#include <usb/ehci-ci.h>
#include <usb/ulpi.h>
#include <wait_bit.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <linux/compat.h>
#include "ehci.h"
struct msm_ehci_priv {
struct ehci_ctrl ctrl; /* Needed by EHCI */
struct usb_ehci *ehci; /* Start of IP core*/
struct ulpi_viewport ulpi_vp; /* ULPI Viewport */
struct phy phy;
};
static int msm_init_after_reset(struct ehci_ctrl *dev)
{
struct msm_ehci_priv *p = container_of(dev, struct msm_ehci_priv, ctrl);
struct usb_ehci *ehci = p->ehci;
generic_phy_reset(&p->phy);
/* set mode to host controller */
writel(CM_HOST, &ehci->usbmode);
return 0;
}
static const struct ehci_ops msm_ehci_ops = {
.init_after_reset = msm_init_after_reset
};
static int ehci_usb_probe(struct udevice *dev)
{
struct msm_ehci_priv *p = dev_get_priv(dev);
struct usb_ehci *ehci = p->ehci;
struct usb_plat *plat = dev_get_plat(dev);
struct ehci_hccr *hccr;
struct ehci_hcor *hcor;
int ret;
hccr = (struct ehci_hccr *)((phys_addr_t)&ehci->caplength);
hcor = (struct ehci_hcor *)((phys_addr_t)hccr +
HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
ret = generic_setup_phy(dev, &p->phy, 0);
if (ret)
return ret;
ret = board_usb_init(0, plat->init_type);
if (ret < 0)
return ret;
return ehci_register(dev, hccr, hcor, &msm_ehci_ops, 0,
plat->init_type);
}
static int ehci_usb_remove(struct udevice *dev)
{
struct msm_ehci_priv *p = dev_get_priv(dev);
struct usb_ehci *ehci = p->ehci;
int ret;
ret = ehci_deregister(dev);
if (ret)
return ret;
/* Stop controller. */
clrbits_le32(&ehci->usbcmd, CMD_RUN);
ret = generic_shutdown_phy(&p->phy);
if (ret)
return ret;
ret = board_usb_init(0, USB_INIT_DEVICE); /* Board specific hook */
if (ret < 0)
return ret;
/* Reset controller */
setbits_le32(&ehci->usbcmd, CMD_RESET);
/* Wait for reset */
if (wait_for_bit_le32(&ehci->usbcmd, CMD_RESET, false, 30, false)) {
printf("Stuck on USB reset.\n");
return -ETIMEDOUT;
}
return 0;
}
static int ehci_usb_of_to_plat(struct udevice *dev)
{
struct msm_ehci_priv *priv = dev_get_priv(dev);
priv->ulpi_vp.port_num = 0;
priv->ehci = dev_read_addr_ptr(dev);
if (priv->ehci == (void *)FDT_ADDR_T_NONE)
return -EINVAL;
/* Warning: this will not work if viewport address is > 64 bit due to
* ULPI design.
*/
priv->ulpi_vp.viewport_addr = (phys_addr_t)&priv->ehci->ulpi_viewpoint;
return 0;
}
static int ehci_usb_of_bind(struct udevice *dev)
{
ofnode ulpi_node = ofnode_first_subnode(dev_ofnode(dev));
ofnode phy_node;
if (!ofnode_valid(ulpi_node))
return 0;
phy_node = ofnode_first_subnode(ulpi_node);
if (!ofnode_valid(phy_node)) {
printf("%s: ulpi subnode with no phy\n", __func__);
return -ENOENT;
}
return device_bind_driver_to_node(dev, "msm8916_usbphy", "msm8916_usbphy",
phy_node, NULL);
}
#if defined(CONFIG_CI_UDC)
/* Little quirk that MSM needs with Chipidea controller
* Must reinit phy after reset
*/
void ci_init_after_reset(struct ehci_ctrl *ctrl)
{
struct msm_ehci_priv *p = ctrl->priv;
generic_phy_reset(&p->phy);
}
#endif
static const struct udevice_id ehci_usb_ids[] = {
{ .compatible = "qcom,ci-hdrc", },
{ }
};
U_BOOT_DRIVER(usb_ehci) = {
.name = "ehci_msm",
.id = UCLASS_USB,
.of_match = ehci_usb_ids,
.of_to_plat = ehci_usb_of_to_plat,
.bind = ehci_usb_of_bind,
.probe = ehci_usb_probe,
.remove = ehci_usb_remove,
.ops = &ehci_usb_ops,
.priv_auto = sizeof(struct msm_ehci_priv),
.plat_auto = sizeof(struct usb_plat),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};