|
@@ -17,10 +17,11 @@
|
|
|
*/
|
|
|
#include <common.h>
|
|
|
#include <dm.h>
|
|
|
+#include <generic-phy.h>
|
|
|
+#include <phy-sun4i-usb.h>
|
|
|
#include <asm/arch/cpu.h>
|
|
|
#include <asm/arch/clock.h>
|
|
|
#include <asm/arch/gpio.h>
|
|
|
-#include <asm/arch/usb_phy.h>
|
|
|
#include <asm-generic/gpio.h>
|
|
|
#include <dm/lists.h>
|
|
|
#include <dm/root.h>
|
|
@@ -86,6 +87,7 @@ struct sunxi_glue {
|
|
|
struct sunxi_ccm_reg *ccm;
|
|
|
struct sunxi_musb_config *cfg;
|
|
|
struct device dev;
|
|
|
+ struct phy *phy;
|
|
|
};
|
|
|
#define to_sunxi_glue(d) container_of(d, struct sunxi_glue, dev)
|
|
|
|
|
@@ -218,6 +220,7 @@ static bool enabled = false;
|
|
|
|
|
|
static int sunxi_musb_enable(struct musb *musb)
|
|
|
{
|
|
|
+ struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
|
|
|
int ret;
|
|
|
|
|
|
pr_debug("%s():\n", __func__);
|
|
@@ -232,17 +235,23 @@ static int sunxi_musb_enable(struct musb *musb)
|
|
|
musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0);
|
|
|
|
|
|
if (is_host_enabled(musb)) {
|
|
|
- ret = sunxi_usb_phy_vbus_detect(0);
|
|
|
+ ret = sun4i_usb_phy_vbus_detect(glue->phy);
|
|
|
if (ret == 1) {
|
|
|
printf("A charger is plugged into the OTG: ");
|
|
|
return -ENODEV;
|
|
|
}
|
|
|
- ret = sunxi_usb_phy_id_detect(0);
|
|
|
+
|
|
|
+ ret = sun4i_usb_phy_id_detect(glue->phy);
|
|
|
if (ret == 1) {
|
|
|
printf("No host cable detected: ");
|
|
|
return -ENODEV;
|
|
|
}
|
|
|
- sunxi_usb_phy_power_on(0); /* port power on */
|
|
|
+
|
|
|
+ ret = generic_phy_power_on(glue->phy);
|
|
|
+ if (ret) {
|
|
|
+ pr_err("failed to power on USB PHY\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
USBC_ForceVbusValidToHigh(musb->mregs);
|
|
@@ -253,13 +262,21 @@ static int sunxi_musb_enable(struct musb *musb)
|
|
|
|
|
|
static void sunxi_musb_disable(struct musb *musb)
|
|
|
{
|
|
|
+ struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
|
|
|
+ int ret;
|
|
|
+
|
|
|
pr_debug("%s():\n", __func__);
|
|
|
|
|
|
if (!enabled)
|
|
|
return;
|
|
|
|
|
|
- if (is_host_enabled(musb))
|
|
|
- sunxi_usb_phy_power_off(0); /* port power off */
|
|
|
+ if (is_host_enabled(musb)) {
|
|
|
+ ret = generic_phy_power_off(glue->phy);
|
|
|
+ if (ret) {
|
|
|
+ pr_err("failed to power off USB PHY\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
USBC_ForceVbusValidToLow(musb->mregs);
|
|
|
mdelay(200); /* Wait for the current session to timeout */
|
|
@@ -270,9 +287,16 @@ static void sunxi_musb_disable(struct musb *musb)
|
|
|
static int sunxi_musb_init(struct musb *musb)
|
|
|
{
|
|
|
struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
|
|
|
+ int ret;
|
|
|
|
|
|
pr_debug("%s():\n", __func__);
|
|
|
|
|
|
+ ret = generic_phy_init(glue->phy);
|
|
|
+ if (ret) {
|
|
|
+ pr_err("failed to init USB PHY\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
musb->isr = sunxi_musb_interrupt;
|
|
|
|
|
|
setbits_le32(&glue->ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_USB0));
|
|
@@ -286,8 +310,6 @@ static int sunxi_musb_init(struct musb *musb)
|
|
|
BIT(glue->cfg->rst_bit));
|
|
|
#endif
|
|
|
|
|
|
- sunxi_usb_phy_init(0);
|
|
|
-
|
|
|
USBC_ConfigFIFO_Base();
|
|
|
USBC_EnableDpDmPullUp(musb->mregs);
|
|
|
USBC_EnableIdPullUp(musb->mregs);
|
|
@@ -383,6 +405,7 @@ static int musb_usb_probe(struct udevice *dev)
|
|
|
struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
|
|
|
struct musb_hdrc_platform_data pdata;
|
|
|
void *base = dev_read_addr_ptr(dev);
|
|
|
+ struct phy phy;
|
|
|
int ret;
|
|
|
|
|
|
if (!base)
|
|
@@ -396,6 +419,13 @@ static int musb_usb_probe(struct udevice *dev)
|
|
|
if (IS_ERR(glue->ccm))
|
|
|
return PTR_ERR(glue->ccm);
|
|
|
|
|
|
+ ret = generic_phy_get_by_name(dev, "usb", &phy);
|
|
|
+ if (ret) {
|
|
|
+ pr_err("failed to get usb PHY\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ glue->phy = &phy;
|
|
|
priv->desc_before_addr = true;
|
|
|
|
|
|
memset(&pdata, 0, sizeof(pdata));
|
|
@@ -426,10 +456,18 @@ static int musb_usb_remove(struct udevice *dev)
|
|
|
{
|
|
|
struct sunxi_glue *glue = dev_get_priv(dev);
|
|
|
struct musb_host_data *host = &glue->mdata;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (generic_phy_valid(glue->phy)) {
|
|
|
+ ret = generic_phy_exit(glue->phy);
|
|
|
+ if (ret) {
|
|
|
+ pr_err("failed to exit %s USB PHY\n", dev->name);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
musb_stop(host->host);
|
|
|
|
|
|
- sunxi_usb_phy_exit(0);
|
|
|
#ifdef CONFIG_SUNXI_GEN_SUN6I
|
|
|
clrbits_le32(&glue->ccm->ahb_reset0_cfg, BIT(AHB_GATE_OFFSET_USB0));
|
|
|
if (glue->cfg->rst_bit)
|