Message ID | 20170302151156.49295-2-icenowy@aosc.xyz (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi, On Thu, Mar 2, 2017 at 11:11 PM, Icenowy Zheng <icenowy@aosc.xyz> wrote: > On newer Allwinner SoCs (H3 and after), the PHY0 node is routed to both > MUSB controller for peripheral and host support (the host support is > slightly broken), and a pair of EHCI/OHCI controllers, which provide a > better support for host mode. > > Add support for automatically switch the route of PHY0 according to the > status of dr_mode and id det pin. > > Only H3 have this function enabled in this patch, as further SoCs will > be tested later and then have it enabled. > > Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz> > --- > Changes in v2: > - Re-route after force session end. > - Drop id_det based on role code in reroute function, as we already > properly set id_det in id_det getting function. > > drivers/phy/phy-sun4i-usb.c | 50 ++++++++++++++++++++++++++++++--------------- > 1 file changed, 33 insertions(+), 17 deletions(-) > > diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c > index a21b5f24a340..b4458878ece7 100644 > --- a/drivers/phy/phy-sun4i-usb.c > +++ b/drivers/phy/phy-sun4i-usb.c > @@ -49,12 +49,14 @@ > #define REG_PHYBIST 0x08 > #define REG_PHYTUNE 0x0c > #define REG_PHYCTL_A33 0x10 > -#define REG_PHY_UNK_H3 0x20 > +#define REG_PHY_OTGCTL 0x20 > > #define REG_PMU_UNK1 0x10 > > #define PHYCTL_DATA BIT(7) > > +#define OTGCTL_ROUTE_MUSB BIT(0) > + > #define SUNXI_AHB_ICHR8_EN BIT(10) > #define SUNXI_AHB_INCR4_BURST_EN BIT(9) > #define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) > @@ -110,6 +112,7 @@ struct sun4i_usb_phy_cfg { > u8 phyctl_offset; > bool dedicated_clocks; > bool enable_pmu_unk1; > + bool phy0_dual_route; > }; > > struct sun4i_usb_phy_data { > @@ -271,23 +274,16 @@ static int sun4i_usb_phy_init(struct phy *_phy) > writel(val & ~2, phy->pmu + REG_PMU_UNK1); > } > > - if (data->cfg->type == sun8i_h3_phy) { > - if (phy->index == 0) { > - val = readl(data->base + REG_PHY_UNK_H3); > - writel(val & ~1, data->base + REG_PHY_UNK_H3); > - } > - } else { > - /* Enable USB 45 Ohm resistor calibration */ > - if (phy->index == 0) > - sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); > + /* Enable USB 45 Ohm resistor calibration */ > + if (phy->index == 0) > + sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); > > - /* Adjust PHY's magnitude and rate */ > - sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); > + /* Adjust PHY's magnitude and rate */ > + sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); > > - /* Disconnect threshold adjustment */ > - sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, > - data->cfg->disc_thresh, 2); > - } > + /* Disconnect threshold adjustment */ > + sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, > + data->cfg->disc_thresh, 2); > > sun4i_usb_phy_passby(phy, 1); > > @@ -486,6 +482,21 @@ static const struct phy_ops sun4i_usb_phy_ops = { > .owner = THIS_MODULE, > }; > > +static void sun4i_usb_phy0_reroute(struct sun4i_usb_phy_data *data, int id_det) > +{ > + u32 regval; > + > + regval = readl(data->base + REG_PHY_OTGCTL); > + if (id_det == 0) { > + /* Host mode. Route phy0 to EHCI/OHCI */ > + regval &= ~OTGCTL_ROUTE_MUSB; > + } else { > + /* Peripheral mode. Route phy0 to MUSB */ > + regval |= OTGCTL_ROUTE_MUSB; > + } > + writel(regval, data->base + REG_PHY_OTGCTL); > +} > + > static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) > { > struct sun4i_usb_phy_data *data = > @@ -546,6 +557,10 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) > sun4i_usb_phy0_set_vbus_detect(phy0, 1); > mutex_unlock(&phy0->mutex); > } > + > + /* Re-route PHY0 if necessary */ > + if (data->cfg->phy0_dual_route) > + sun4i_usb_phy0_reroute(data, id_det); > } > > if (vbus_notify) > @@ -700,7 +715,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) > return PTR_ERR(phy->reset); > } > > - if (i) { /* No pmu for usbc0 */ > + if (i || data->cfg->phy0_dual_route) { /* No pmu for musb */ > snprintf(name, sizeof(name), "pmu%d", i); This is part of the binding. Please update it to list "pmu0" reg/reg-names for applicable SoCs. Otherwise, Acked-by: Chen-Yu Tsai <wens@csie.org> > res = platform_get_resource_byname(pdev, > IORESOURCE_MEM, name); > @@ -825,6 +840,7 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { > .disc_thresh = 3, > .dedicated_clocks = true, > .enable_pmu_unk1 = true, > + .phy0_dual_route = true, > }; > > static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = { > -- > 2.11.1 >
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index a21b5f24a340..b4458878ece7 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -49,12 +49,14 @@ #define REG_PHYBIST 0x08 #define REG_PHYTUNE 0x0c #define REG_PHYCTL_A33 0x10 -#define REG_PHY_UNK_H3 0x20 +#define REG_PHY_OTGCTL 0x20 #define REG_PMU_UNK1 0x10 #define PHYCTL_DATA BIT(7) +#define OTGCTL_ROUTE_MUSB BIT(0) + #define SUNXI_AHB_ICHR8_EN BIT(10) #define SUNXI_AHB_INCR4_BURST_EN BIT(9) #define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) @@ -110,6 +112,7 @@ struct sun4i_usb_phy_cfg { u8 phyctl_offset; bool dedicated_clocks; bool enable_pmu_unk1; + bool phy0_dual_route; }; struct sun4i_usb_phy_data { @@ -271,23 +274,16 @@ static int sun4i_usb_phy_init(struct phy *_phy) writel(val & ~2, phy->pmu + REG_PMU_UNK1); } - if (data->cfg->type == sun8i_h3_phy) { - if (phy->index == 0) { - val = readl(data->base + REG_PHY_UNK_H3); - writel(val & ~1, data->base + REG_PHY_UNK_H3); - } - } else { - /* Enable USB 45 Ohm resistor calibration */ - if (phy->index == 0) - sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); + /* Enable USB 45 Ohm resistor calibration */ + if (phy->index == 0) + sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); - /* Adjust PHY's magnitude and rate */ - sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); + /* Adjust PHY's magnitude and rate */ + sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); - /* Disconnect threshold adjustment */ - sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, - data->cfg->disc_thresh, 2); - } + /* Disconnect threshold adjustment */ + sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, + data->cfg->disc_thresh, 2); sun4i_usb_phy_passby(phy, 1); @@ -486,6 +482,21 @@ static const struct phy_ops sun4i_usb_phy_ops = { .owner = THIS_MODULE, }; +static void sun4i_usb_phy0_reroute(struct sun4i_usb_phy_data *data, int id_det) +{ + u32 regval; + + regval = readl(data->base + REG_PHY_OTGCTL); + if (id_det == 0) { + /* Host mode. Route phy0 to EHCI/OHCI */ + regval &= ~OTGCTL_ROUTE_MUSB; + } else { + /* Peripheral mode. Route phy0 to MUSB */ + regval |= OTGCTL_ROUTE_MUSB; + } + writel(regval, data->base + REG_PHY_OTGCTL); +} + static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) { struct sun4i_usb_phy_data *data = @@ -546,6 +557,10 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) sun4i_usb_phy0_set_vbus_detect(phy0, 1); mutex_unlock(&phy0->mutex); } + + /* Re-route PHY0 if necessary */ + if (data->cfg->phy0_dual_route) + sun4i_usb_phy0_reroute(data, id_det); } if (vbus_notify) @@ -700,7 +715,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) return PTR_ERR(phy->reset); } - if (i) { /* No pmu for usbc0 */ + if (i || data->cfg->phy0_dual_route) { /* No pmu for musb */ snprintf(name, sizeof(name), "pmu%d", i); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); @@ -825,6 +840,7 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { .disc_thresh = 3, .dedicated_clocks = true, .enable_pmu_unk1 = true, + .phy0_dual_route = true, }; static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
On newer Allwinner SoCs (H3 and after), the PHY0 node is routed to both MUSB controller for peripheral and host support (the host support is slightly broken), and a pair of EHCI/OHCI controllers, which provide a better support for host mode. Add support for automatically switch the route of PHY0 according to the status of dr_mode and id det pin. Only H3 have this function enabled in this patch, as further SoCs will be tested later and then have it enabled. Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz> --- Changes in v2: - Re-route after force session end. - Drop id_det based on role code in reroute function, as we already properly set id_det in id_det getting function. drivers/phy/phy-sun4i-usb.c | 50 ++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 17 deletions(-)