mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-09-30 16:40:44 +09:00
phy: sun4i-usb: Add A83T USB PHY config
Unlike, other Allwinner SUN4I Phy supporting SOC, A83T has 2 USB PHY's and second one is HSIC. So phy control need to configure to handle these HSIC and SIDDQ requirement. Signed-off-by: Jagan Teki <jagan@amarulasolutions.com> Acked-by: Jun Nie <jun.nie@linaro.org>
This commit is contained in:
parent
bafe5e3061
commit
5f646bf1d7
@ -53,9 +53,19 @@
|
||||
#define SUNXI_AHB_INCRX_ALIGN_EN BIT(8)
|
||||
#define SUNXI_ULPI_BYPASS_EN BIT(0)
|
||||
|
||||
/* A83T specific control bits for PHY0 */
|
||||
#define PHY_CTL_VBUSVLDEXT BIT(5)
|
||||
#define PHY_CTL_SIDDQ BIT(3)
|
||||
|
||||
/* A83T specific control bits for PHY2 HSIC */
|
||||
#define SUNXI_EHCI_HS_FORCE BIT(20)
|
||||
#define SUNXI_HSIC_CONNECT_INT BIT(16)
|
||||
#define SUNXI_HSIC BIT(1)
|
||||
|
||||
#define MAX_PHYS 4
|
||||
|
||||
enum sun4i_usb_phy_type {
|
||||
sun8i_a83t_phy,
|
||||
sun8i_h3_phy,
|
||||
sun8i_v3s_phy,
|
||||
sun50i_a64_phy,
|
||||
@ -92,13 +102,20 @@ struct sun4i_usb_phy_info {
|
||||
.gpio_vbus = CONFIG_USB2_VBUS_PIN,
|
||||
.gpio_vbus_det = NULL,
|
||||
.gpio_id_det = NULL,
|
||||
#ifdef CONFIG_MACH_SUN8I_A83T
|
||||
.rst_mask = (CCM_USB_CTRL_HSIC_RST | CCM_USB_CTRL_HSIC_CLK |
|
||||
CCM_USB_CTRL_12M_CLK),
|
||||
#else
|
||||
.rst_mask = (CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK),
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.gpio_vbus = CONFIG_USB3_VBUS_PIN,
|
||||
.gpio_vbus_det = NULL,
|
||||
.gpio_id_det = NULL,
|
||||
#ifdef CONFIG_MACH_SUN6I
|
||||
.rst_mask = (CCM_USB_CTRL_PHY3_RST | CCM_USB_CTRL_PHY3_CLK),
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
@ -166,9 +183,10 @@ static void sun4i_usb_phy_write(struct phy *phy, u32 addr, u32 data, int len)
|
||||
}
|
||||
}
|
||||
|
||||
static void sun4i_usb_phy_passby(struct sun4i_usb_phy_plat *usb_phy,
|
||||
bool enable)
|
||||
static void sun4i_usb_phy_passby(struct phy *phy, bool enable)
|
||||
{
|
||||
struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
|
||||
struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
|
||||
u32 bits, reg_value;
|
||||
|
||||
if (!usb_phy->pmu)
|
||||
@ -176,6 +194,12 @@ static void sun4i_usb_phy_passby(struct sun4i_usb_phy_plat *usb_phy,
|
||||
|
||||
bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
|
||||
SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
|
||||
|
||||
/* A83T USB2 is HSIC */
|
||||
if (data->cfg->type == sun8i_a83t_phy && usb_phy->id == 2)
|
||||
bits |= SUNXI_EHCI_HS_FORCE | SUNXI_HSIC_CONNECT_INT |
|
||||
SUNXI_HSIC;
|
||||
|
||||
reg_value = readl(usb_phy->pmu);
|
||||
|
||||
if (enable)
|
||||
@ -244,25 +268,36 @@ static int sun4i_usb_phy_init(struct phy *phy)
|
||||
|
||||
setbits_le32(&data->ccm->usb_clk_cfg, usb_phy->rst_mask);
|
||||
|
||||
if (usb_phy->pmu && data->cfg->enable_pmu_unk1) {
|
||||
val = readl(usb_phy->pmu + REG_PMU_UNK1);
|
||||
writel(val & ~2, usb_phy->pmu + REG_PMU_UNK1);
|
||||
if (data->cfg->type == sun8i_a83t_phy) {
|
||||
if (phy->id == 0) {
|
||||
val = readl(data->base + data->cfg->phyctl_offset);
|
||||
val |= PHY_CTL_VBUSVLDEXT;
|
||||
val &= ~PHY_CTL_SIDDQ;
|
||||
writel(val, data->base + data->cfg->phyctl_offset);
|
||||
}
|
||||
} else {
|
||||
if (usb_phy->pmu && data->cfg->enable_pmu_unk1) {
|
||||
val = readl(usb_phy->pmu + REG_PMU_UNK1);
|
||||
writel(val & ~2, usb_phy->pmu + REG_PMU_UNK1);
|
||||
}
|
||||
|
||||
if (usb_phy->id == 0)
|
||||
sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN,
|
||||
PHY_RES45_CAL_DATA,
|
||||
PHY_RES45_CAL_LEN);
|
||||
|
||||
/* Adjust PHY's magnitude and rate */
|
||||
sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE,
|
||||
PHY_TX_MAGNITUDE | PHY_TX_RATE,
|
||||
PHY_TX_AMPLITUDE_LEN);
|
||||
|
||||
/* Disconnect threshold adjustment */
|
||||
sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL,
|
||||
data->cfg->disc_thresh, PHY_DISCON_TH_LEN);
|
||||
}
|
||||
|
||||
if (usb_phy->id == 0)
|
||||
sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, PHY_RES45_CAL_DATA,
|
||||
PHY_RES45_CAL_LEN);
|
||||
|
||||
/* Adjust PHY's magnitude and rate */
|
||||
sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, PHY_TX_MAGNITUDE |
|
||||
PHY_TX_RATE, PHY_TX_AMPLITUDE_LEN);
|
||||
|
||||
/* Disconnect threshold adjustment */
|
||||
sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, data->cfg->disc_thresh,
|
||||
PHY_DISCON_TH_LEN);
|
||||
|
||||
if (usb_phy->id != 0)
|
||||
sun4i_usb_phy_passby(usb_phy, true);
|
||||
sun4i_usb_phy_passby(phy, true);
|
||||
|
||||
sun4i_usb_phy0_reroute(data, true);
|
||||
|
||||
@ -274,7 +309,16 @@ static int sun4i_usb_phy_exit(struct phy *phy)
|
||||
struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
|
||||
struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
|
||||
|
||||
sun4i_usb_phy_passby(usb_phy, false);
|
||||
if (phy->id == 0) {
|
||||
if (data->cfg->type == sun8i_a83t_phy) {
|
||||
void __iomem *phyctl = data->base +
|
||||
data->cfg->phyctl_offset;
|
||||
|
||||
writel(readl(phyctl) | PHY_CTL_SIDDQ, phyctl);
|
||||
}
|
||||
}
|
||||
|
||||
sun4i_usb_phy_passby(phy, false);
|
||||
|
||||
clrbits_le32(&data->ccm->usb_clk_cfg, usb_phy->rst_mask);
|
||||
|
||||
@ -416,6 +460,12 @@ static int sun4i_usb_phy_probe(struct udevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = {
|
||||
.num_phys = 3,
|
||||
.type = sun8i_a83t_phy,
|
||||
.phyctl_offset = REG_PHYCTL_A33,
|
||||
};
|
||||
|
||||
static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
|
||||
.num_phys = 4,
|
||||
.type = sun8i_h3_phy,
|
||||
@ -444,6 +494,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
|
||||
};
|
||||
|
||||
static const struct udevice_id sun4i_usb_phy_ids[] = {
|
||||
{ .compatible = "allwinner,sun8i-a83t-usb-phy", .data = (ulong)&sun8i_a83t_cfg },
|
||||
{ .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg },
|
||||
{ .compatible = "allwinner,sun8i-v3s-usb-phy", .data = (ulong)&sun8i_v3s_cfg },
|
||||
{ .compatible = "allwinner,sun50i-a64-usb-phy", .data = (ulong)&sun50i_a64_cfg},
|
||||
|
Loading…
Reference in New Issue
Block a user