1
0
mirror of https://xff.cz/git/u-boot/ synced 2025-09-01 08:42:12 +02:00
This commit is contained in:
Tom Rini
2024-09-09 15:54:56 -06:00
10 changed files with 131 additions and 18 deletions

View File

@@ -8,6 +8,7 @@
#include <clk.h>
#include <div64.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <fdtdec.h>
#include <generic-phy.h>
#include <malloc.h>
@@ -31,8 +32,13 @@
#define USB2_LINECTRL1 0x610
#define USB2_ADPCTRL 0x630
/* INT_ENABLE */
#define USB2_INT_ENABLE_UCOM_INTEN BIT(3)
#define USB2_INT_ENABLE_USBH_INTB_EN BIT(2)
#define USB2_INT_ENABLE_USBH_INTA_EN BIT(1)
/* USBCTR */
#define USB2_USBCTR_PLL_RST BIT(1)
#define USB2_USBCTR_PLL_RST BIT(1)
/* SPD_RSM_TIMSET */
#define USB2_SPD_RSM_TIMSET_INIT 0x014e029b
@@ -43,11 +49,23 @@
/* COMMCTRL */
#define USB2_COMMCTRL_OTG_PERI BIT(31) /* 1 = Peripheral mode */
/* OBINTSTA and OBINTEN */
#define USB2_OBINT_SESSVLDCHG BIT(12)
#define USB2_OBINT_IDDIGCHG BIT(11)
/* VBCTRL */
#define USB2_VBCTRL_DRVVBUSSEL BIT(8)
/* LINECTRL1 */
#define USB2_LINECTRL1_DPRPD_EN BIT(19)
#define USB2_LINECTRL1_DP_RPD BIT(18)
#define USB2_LINECTRL1_DMRPD_EN BIT(17)
#define USB2_LINECTRL1_DM_RPD BIT(16)
/* ADPCTRL */
#define USB2_ADPCTRL_OTGSESSVLD BIT(20)
#define USB2_ADPCTRL_IDDIG BIT(19)
#define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */
#define USB2_ADPCTRL_DRVVBUS BIT(4)
struct rcar_gen3_phy {
@@ -65,12 +83,14 @@ static int rcar_gen3_phy_phy_init(struct phy *phy)
writel(USB2_SPD_RSM_TIMSET_INIT, priv->regs + USB2_SPD_RSM_TIMSET);
writel(USB2_OC_TIMSET_INIT, priv->regs + USB2_OC_TIMSET);
setbits_le32(priv->regs + USB2_LINECTRL1,
USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
return 0;
}
clrbits_le32(priv->regs + USB2_COMMCTRL, USB2_COMMCTRL_OTG_PERI);
static int rcar_gen3_phy_phy_exit(struct phy *phy)
{
struct rcar_gen3_phy *priv = dev_get_priv(phy->dev);
setbits_le32(priv->regs + USB2_ADPCTRL, USB2_ADPCTRL_DRVVBUS);
writel(0, priv->regs + USB2_INT_ENABLE);
return 0;
}
@@ -102,10 +122,70 @@ static int rcar_gen3_phy_phy_power_off(struct phy *phy)
return regulator_set_enable(priv->vbus_supply, false);
}
static int rcar_gen3_phy_phy_set_mode(struct phy *phy, enum phy_mode mode,
int submode)
{
const u32 adpdevmask = USB2_ADPCTRL_IDDIG | USB2_ADPCTRL_OTGSESSVLD;
struct rcar_gen3_phy *priv = dev_get_priv(phy->dev);
u32 adpctrl;
if (mode == PHY_MODE_USB_OTG) {
if (submode) {
/* OTG submode is used as initialization indicator */
writel(USB2_INT_ENABLE_UCOM_INTEN |
USB2_INT_ENABLE_USBH_INTB_EN |
USB2_INT_ENABLE_USBH_INTA_EN,
priv->regs + USB2_INT_ENABLE);
setbits_le32(priv->regs + USB2_VBCTRL,
USB2_VBCTRL_DRVVBUSSEL);
writel(USB2_OBINT_SESSVLDCHG | USB2_OBINT_IDDIGCHG,
priv->regs + USB2_OBINTSTA);
setbits_le32(priv->regs + USB2_OBINTEN,
USB2_OBINT_SESSVLDCHG |
USB2_OBINT_IDDIGCHG);
setbits_le32(priv->regs + USB2_ADPCTRL,
USB2_ADPCTRL_IDPULLUP);
clrsetbits_le32(priv->regs + USB2_LINECTRL1,
USB2_LINECTRL1_DP_RPD |
USB2_LINECTRL1_DM_RPD |
USB2_LINECTRL1_DPRPD_EN |
USB2_LINECTRL1_DMRPD_EN,
USB2_LINECTRL1_DPRPD_EN |
USB2_LINECTRL1_DMRPD_EN);
}
adpctrl = readl(priv->regs + USB2_ADPCTRL);
if ((adpctrl & adpdevmask) == adpdevmask)
mode = PHY_MODE_USB_DEVICE;
else
mode = PHY_MODE_USB_HOST;
}
if (mode == PHY_MODE_USB_HOST) {
clrbits_le32(priv->regs + USB2_COMMCTRL, USB2_COMMCTRL_OTG_PERI);
setbits_le32(priv->regs + USB2_LINECTRL1,
USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
setbits_le32(priv->regs + USB2_ADPCTRL, USB2_ADPCTRL_DRVVBUS);
} else if (mode == PHY_MODE_USB_DEVICE) {
setbits_le32(priv->regs + USB2_COMMCTRL, USB2_COMMCTRL_OTG_PERI);
clrsetbits_le32(priv->regs + USB2_LINECTRL1,
USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD,
USB2_LINECTRL1_DM_RPD);
clrbits_le32(priv->regs + USB2_ADPCTRL, USB2_ADPCTRL_DRVVBUS);
} else {
dev_err(phy->dev, "Unknown mode %d\n", mode);
return -EINVAL;
}
return 0;
}
static const struct phy_ops rcar_gen3_phy_phy_ops = {
.init = rcar_gen3_phy_phy_init,
.exit = rcar_gen3_phy_phy_exit,
.power_on = rcar_gen3_phy_phy_power_on,
.power_off = rcar_gen3_phy_phy_power_off,
.set_mode = rcar_gen3_phy_phy_set_mode,
};
static int rcar_gen3_phy_probe(struct udevice *dev)

View File

@@ -508,7 +508,8 @@ int generic_phy_power_off_bulk(struct phy_bulk *bulk)
return ret;
}
int generic_setup_phy(struct udevice *dev, struct phy *phy, int index)
int generic_setup_phy(struct udevice *dev, struct phy *phy, int index,
enum phy_mode mode, int submode)
{
int ret;
@@ -520,10 +521,18 @@ int generic_setup_phy(struct udevice *dev, struct phy *phy, int index)
if (ret)
return ret;
ret = generic_phy_set_mode(phy, mode, submode);
if (ret)
goto phys_mode_err;
ret = generic_phy_power_on(phy);
if (ret)
generic_phy_exit(phy);
goto phys_mode_err;
return 0;
phys_mode_err:
generic_phy_exit(phy);
return ret;
}

View File

@@ -72,6 +72,18 @@ static int sandbox_phy_exit(struct phy *phy)
return 0;
}
static int
sandbox_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
{
if (submode)
return -EOPNOTSUPP;
if (mode != PHY_MODE_USB_HOST)
return -EINVAL;
return 0;
}
static int sandbox_phy_bind(struct udevice *dev)
{
if (dev_get_driver_data(dev) != DRIVER_DATA)
@@ -96,6 +108,7 @@ static struct phy_ops sandbox_phy_ops = {
.power_off = sandbox_phy_power_off,
.init = sandbox_phy_init,
.exit = sandbox_phy_exit,
.set_mode = sandbox_phy_set_mode,
};
static const struct udevice_id sandbox_phy_ids[] = {

View File

@@ -94,7 +94,7 @@ static int ehci_usb_probe(struct udevice *dev)
if (err)
goto reset_err;
err = generic_setup_phy(dev, &priv->phy, 0);
err = generic_setup_phy(dev, &priv->phy, 0, PHY_MODE_USB_HOST, 0);
if (err)
goto regulator_err;

View File

@@ -80,7 +80,7 @@ static int ehci_usb_probe(struct udevice *dev)
hcor = (struct ehci_hcor *)((phys_addr_t)hccr +
HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
ret = generic_setup_phy(dev, &p->phy, 0);
ret = generic_setup_phy(dev, &p->phy, 0, PHY_MODE_USB_HOST, 0);
if (ret)
goto cleanup_iface;

View File

@@ -703,7 +703,7 @@ static int ehci_usb_probe(struct udevice *dev)
usb_phy_enable(ehci, priv->phy_addr);
#endif
#else
ret = generic_setup_phy(dev, &priv->phy, 0);
ret = generic_setup_phy(dev, &priv->phy, 0, PHY_MODE_USB_HOST, 0);
if (ret)
goto err_regulator;
#endif

View File

@@ -30,7 +30,7 @@ static int ehci_pci_init(struct udevice *dev, struct ehci_hccr **ret_hccr,
int ret;
u32 cmd;
ret = generic_setup_phy(dev, &priv->phy, 0);
ret = generic_setup_phy(dev, &priv->phy, 0, PHY_MODE_USB_HOST, 0);
if (ret)
return ret;

View File

@@ -50,7 +50,7 @@ static int ohci_usb_probe(struct udevice *dev)
goto reset_err;
}
err = generic_setup_phy(dev, &priv->phy, 0);
err = generic_setup_phy(dev, &priv->phy, 0, PHY_MODE_USB_HOST, 0);
if (err)
goto reset_err;

View File

@@ -415,10 +415,13 @@ int generic_phy_power_off_bulk(struct phy_bulk *bulk);
* @dev: The consumer device.
* @phy: A pointer to the PHY port
* @index: The index in the list of available PHYs
* @mode: PHY mode
* @submode: PHY submode
*
* Return: 0 if OK, or negative error code.
*/
int generic_setup_phy(struct udevice *dev, struct phy *phy, int index);
int generic_setup_phy(struct udevice *dev, struct phy *phy, int index,
enum phy_mode mode, int submode);
/**
* generic_shutdown_phy() - Power off and de-initialize phy.
@@ -509,7 +512,8 @@ static inline int generic_phy_power_off_bulk(struct phy_bulk *bulk)
return 0;
}
static inline int generic_setup_phy(struct udevice *dev, struct phy *phy, int index)
static inline int generic_setup_phy(struct udevice *dev, struct phy *phy, int index,
enum phy_mode mode, int submode)
{
return 0;
}

View File

@@ -243,20 +243,27 @@ static int dm_test_phy_setup(struct unit_test_state *uts)
"gen_phy_user", &parent));
/* normal */
ut_assertok(generic_setup_phy(parent, &phy, 0));
ut_assertok(generic_setup_phy(parent, &phy, 0, PHY_MODE_USB_HOST, 0));
ut_assertok(generic_shutdown_phy(&phy));
/* set_mode as USB Host passes, anything else is not supported */
ut_assertok(generic_setup_phy(parent, &phy, 0, PHY_MODE_USB_HOST, 0));
ut_assertok(generic_phy_set_mode(&phy, PHY_MODE_USB_HOST, 0));
ut_asserteq(-EOPNOTSUPP, generic_phy_set_mode(&phy, PHY_MODE_USB_HOST, 1));
ut_asserteq(-EINVAL, generic_phy_set_mode(&phy, PHY_MODE_USB_DEVICE, 0));
ut_assertok(generic_shutdown_phy(&phy));
/* power_off fail with -EIO */
ut_assertok(generic_setup_phy(parent, &phy, 1));
ut_assertok(generic_setup_phy(parent, &phy, 1, PHY_MODE_USB_HOST, 0));
ut_asserteq(-EIO, generic_shutdown_phy(&phy));
/* power_on fail with -EIO */
ut_asserteq(-EIO, generic_setup_phy(parent, &phy, 2));
ut_asserteq(-EIO, generic_setup_phy(parent, &phy, 2, PHY_MODE_USB_HOST, 0));
ut_assertok(generic_shutdown_phy(&phy));
/* generic_phy_get_by_index fail with -ENOENT */
ut_asserteq(-ENOENT, generic_phy_get_by_index(parent, 3, &phy));
ut_assertok(generic_setup_phy(parent, &phy, 3));
ut_assertok(generic_setup_phy(parent, &phy, 3, PHY_MODE_USB_HOST, 0));
ut_assertok(generic_shutdown_phy(&phy));
return 0;