mirror of
https://xff.cz/git/u-boot/
synced 2025-09-19 09:32:07 +02:00
Merge branch 'next' of https://source.denx.de/u-boot/custodians/u-boot-usb into next
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
#include <clk.h>
|
#include <clk.h>
|
||||||
#include <div64.h>
|
#include <div64.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
#include <dm/device_compat.h>
|
||||||
#include <fdtdec.h>
|
#include <fdtdec.h>
|
||||||
#include <generic-phy.h>
|
#include <generic-phy.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
@@ -31,8 +32,13 @@
|
|||||||
#define USB2_LINECTRL1 0x610
|
#define USB2_LINECTRL1 0x610
|
||||||
#define USB2_ADPCTRL 0x630
|
#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 */
|
/* USBCTR */
|
||||||
#define USB2_USBCTR_PLL_RST BIT(1)
|
#define USB2_USBCTR_PLL_RST BIT(1)
|
||||||
|
|
||||||
/* SPD_RSM_TIMSET */
|
/* SPD_RSM_TIMSET */
|
||||||
#define USB2_SPD_RSM_TIMSET_INIT 0x014e029b
|
#define USB2_SPD_RSM_TIMSET_INIT 0x014e029b
|
||||||
@@ -43,11 +49,23 @@
|
|||||||
/* COMMCTRL */
|
/* COMMCTRL */
|
||||||
#define USB2_COMMCTRL_OTG_PERI BIT(31) /* 1 = Peripheral mode */
|
#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 */
|
/* LINECTRL1 */
|
||||||
|
#define USB2_LINECTRL1_DPRPD_EN BIT(19)
|
||||||
#define USB2_LINECTRL1_DP_RPD BIT(18)
|
#define USB2_LINECTRL1_DP_RPD BIT(18)
|
||||||
|
#define USB2_LINECTRL1_DMRPD_EN BIT(17)
|
||||||
#define USB2_LINECTRL1_DM_RPD BIT(16)
|
#define USB2_LINECTRL1_DM_RPD BIT(16)
|
||||||
|
|
||||||
/* ADPCTRL */
|
/* 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)
|
#define USB2_ADPCTRL_DRVVBUS BIT(4)
|
||||||
|
|
||||||
struct rcar_gen3_phy {
|
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_SPD_RSM_TIMSET_INIT, priv->regs + USB2_SPD_RSM_TIMSET);
|
||||||
writel(USB2_OC_TIMSET_INIT, priv->regs + USB2_OC_TIMSET);
|
writel(USB2_OC_TIMSET_INIT, priv->regs + USB2_OC_TIMSET);
|
||||||
|
|
||||||
setbits_le32(priv->regs + USB2_LINECTRL1,
|
return 0;
|
||||||
USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
|
}
|
||||||
|
|
||||||
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;
|
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);
|
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 = {
|
static const struct phy_ops rcar_gen3_phy_phy_ops = {
|
||||||
.init = rcar_gen3_phy_phy_init,
|
.init = rcar_gen3_phy_phy_init,
|
||||||
|
.exit = rcar_gen3_phy_phy_exit,
|
||||||
.power_on = rcar_gen3_phy_phy_power_on,
|
.power_on = rcar_gen3_phy_phy_power_on,
|
||||||
.power_off = rcar_gen3_phy_phy_power_off,
|
.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)
|
static int rcar_gen3_phy_probe(struct udevice *dev)
|
||||||
|
@@ -508,7 +508,8 @@ int generic_phy_power_off_bulk(struct phy_bulk *bulk)
|
|||||||
return ret;
|
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;
|
int ret;
|
||||||
|
|
||||||
@@ -520,10 +521,18 @@ int generic_setup_phy(struct udevice *dev, struct phy *phy, int index)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
ret = generic_phy_set_mode(phy, mode, submode);
|
||||||
|
if (ret)
|
||||||
|
goto phys_mode_err;
|
||||||
|
|
||||||
ret = generic_phy_power_on(phy);
|
ret = generic_phy_power_on(phy);
|
||||||
if (ret)
|
if (ret)
|
||||||
generic_phy_exit(phy);
|
goto phys_mode_err;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
phys_mode_err:
|
||||||
|
generic_phy_exit(phy);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -72,6 +72,18 @@ static int sandbox_phy_exit(struct phy *phy)
|
|||||||
return 0;
|
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)
|
static int sandbox_phy_bind(struct udevice *dev)
|
||||||
{
|
{
|
||||||
if (dev_get_driver_data(dev) != DRIVER_DATA)
|
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,
|
.power_off = sandbox_phy_power_off,
|
||||||
.init = sandbox_phy_init,
|
.init = sandbox_phy_init,
|
||||||
.exit = sandbox_phy_exit,
|
.exit = sandbox_phy_exit,
|
||||||
|
.set_mode = sandbox_phy_set_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct udevice_id sandbox_phy_ids[] = {
|
static const struct udevice_id sandbox_phy_ids[] = {
|
||||||
|
@@ -94,7 +94,7 @@ static int ehci_usb_probe(struct udevice *dev)
|
|||||||
if (err)
|
if (err)
|
||||||
goto reset_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)
|
if (err)
|
||||||
goto regulator_err;
|
goto regulator_err;
|
||||||
|
|
||||||
|
@@ -80,7 +80,7 @@ static int ehci_usb_probe(struct udevice *dev)
|
|||||||
hcor = (struct ehci_hcor *)((phys_addr_t)hccr +
|
hcor = (struct ehci_hcor *)((phys_addr_t)hccr +
|
||||||
HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
|
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)
|
if (ret)
|
||||||
goto cleanup_iface;
|
goto cleanup_iface;
|
||||||
|
|
||||||
|
@@ -703,7 +703,7 @@ static int ehci_usb_probe(struct udevice *dev)
|
|||||||
usb_phy_enable(ehci, priv->phy_addr);
|
usb_phy_enable(ehci, priv->phy_addr);
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
ret = generic_setup_phy(dev, &priv->phy, 0);
|
ret = generic_setup_phy(dev, &priv->phy, 0, PHY_MODE_USB_HOST, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_regulator;
|
goto err_regulator;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -30,7 +30,7 @@ static int ehci_pci_init(struct udevice *dev, struct ehci_hccr **ret_hccr,
|
|||||||
int ret;
|
int ret;
|
||||||
u32 cmd;
|
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)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@@ -50,7 +50,7 @@ static int ohci_usb_probe(struct udevice *dev)
|
|||||||
goto reset_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)
|
if (err)
|
||||||
goto reset_err;
|
goto reset_err;
|
||||||
|
|
||||||
|
@@ -415,10 +415,13 @@ int generic_phy_power_off_bulk(struct phy_bulk *bulk);
|
|||||||
* @dev: The consumer device.
|
* @dev: The consumer device.
|
||||||
* @phy: A pointer to the PHY port
|
* @phy: A pointer to the PHY port
|
||||||
* @index: The index in the list of available PHYs
|
* @index: The index in the list of available PHYs
|
||||||
|
* @mode: PHY mode
|
||||||
|
* @submode: PHY submode
|
||||||
*
|
*
|
||||||
* Return: 0 if OK, or negative error code.
|
* 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.
|
* 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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -243,20 +243,27 @@ static int dm_test_phy_setup(struct unit_test_state *uts)
|
|||||||
"gen_phy_user", &parent));
|
"gen_phy_user", &parent));
|
||||||
|
|
||||||
/* normal */
|
/* 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));
|
ut_assertok(generic_shutdown_phy(&phy));
|
||||||
|
|
||||||
/* power_off fail with -EIO */
|
/* 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));
|
ut_asserteq(-EIO, generic_shutdown_phy(&phy));
|
||||||
|
|
||||||
/* power_on fail with -EIO */
|
/* 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));
|
ut_assertok(generic_shutdown_phy(&phy));
|
||||||
|
|
||||||
/* generic_phy_get_by_index fail with -ENOENT */
|
/* generic_phy_get_by_index fail with -ENOENT */
|
||||||
ut_asserteq(-ENOENT, generic_phy_get_by_index(parent, 3, &phy));
|
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));
|
ut_assertok(generic_shutdown_phy(&phy));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user