mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-25 14:56:03 +00:00
phy: sun4i-usb: Add a sunxi specific function for setting squelch-detect
The sunxi otg phy has a bug where it wrongly detects a high speed squelch when reset on the root port gets de-asserted with a lo-speed device. The workaround for this is to disable squelch detect before de-asserting reset, and re-enabling it after the reset de-assert is done. Add a sunxi specific phy function to allow the sunxi-musb glue to do this. Signed-off-by: Jagan Teki <jagan@amarulasolutions.com> Acked-by: Jun Nie <jun.nie@linaro.org>
This commit is contained in:
parent
237050fc62
commit
aa29b11b3f
5 changed files with 42 additions and 11 deletions
|
@ -36,6 +36,7 @@
|
||||||
#define PHY_TX_AMPLITUDE_TUNE 0x20
|
#define PHY_TX_AMPLITUDE_TUNE 0x20
|
||||||
#define PHY_TX_SLEWRATE_TUNE 0x22
|
#define PHY_TX_SLEWRATE_TUNE 0x22
|
||||||
#define PHY_DISCON_TH_SEL 0x2a
|
#define PHY_DISCON_TH_SEL 0x2a
|
||||||
|
#define PHY_SQUELCH_DETECT 0x3c
|
||||||
|
|
||||||
#define PHYCTL_DATA BIT(7)
|
#define PHYCTL_DATA BIT(7)
|
||||||
#define OTGCTL_ROUTE_MUSB BIT(0)
|
#define OTGCTL_ROUTE_MUSB BIT(0)
|
||||||
|
@ -383,6 +384,11 @@ int sun4i_usb_phy_id_detect(struct phy *phy)
|
||||||
return gpio_get_value(usb_phy->gpio_id_det);
|
return gpio_get_value(usb_phy->gpio_id_det);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sun4i_usb_phy_set_squelch_detect(struct phy *phy, bool enabled)
|
||||||
|
{
|
||||||
|
sun4i_usb_phy_write(phy, PHY_SQUELCH_DETECT, enabled ? 0 : 2, 2);
|
||||||
|
}
|
||||||
|
|
||||||
static struct phy_ops sun4i_usb_phy_ops = {
|
static struct phy_ops sun4i_usb_phy_ops = {
|
||||||
.of_xlate = sun4i_usb_phy_xlate,
|
.of_xlate = sun4i_usb_phy_xlate,
|
||||||
.init = sun4i_usb_phy_init,
|
.init = sun4i_usb_phy_init,
|
||||||
|
|
|
@ -200,6 +200,8 @@ enum musb_g_ep0_state {
|
||||||
* @vbus_status: returns vbus status if possible
|
* @vbus_status: returns vbus status if possible
|
||||||
* @set_vbus: forces vbus status
|
* @set_vbus: forces vbus status
|
||||||
* @adjust_channel_params: pre check for standard dma channel_program func
|
* @adjust_channel_params: pre check for standard dma channel_program func
|
||||||
|
* @pre_root_reset_end: called before the root usb port reset flag gets cleared
|
||||||
|
* @post_root_reset_end: called after the root usb port reset flag gets cleared
|
||||||
*/
|
*/
|
||||||
struct musb_platform_ops {
|
struct musb_platform_ops {
|
||||||
int (*init)(struct musb *musb);
|
int (*init)(struct musb *musb);
|
||||||
|
@ -221,6 +223,8 @@ struct musb_platform_ops {
|
||||||
int (*adjust_channel_params)(struct dma_channel *channel,
|
int (*adjust_channel_params)(struct dma_channel *channel,
|
||||||
u16 packet_sz, u8 *mode,
|
u16 packet_sz, u8 *mode,
|
||||||
dma_addr_t *dma_addr, u32 *len);
|
dma_addr_t *dma_addr, u32 *len);
|
||||||
|
void (*pre_root_reset_end)(struct musb *musb);
|
||||||
|
void (*post_root_reset_end)(struct musb *musb);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -193,19 +193,16 @@ static int _musb_reset_root_port(struct musb_host_data *host,
|
||||||
power &= 0xf0;
|
power &= 0xf0;
|
||||||
musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
|
musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
|
||||||
mdelay(50);
|
mdelay(50);
|
||||||
#ifdef CONFIG_ARCH_SUNXI
|
|
||||||
/*
|
if (host->host->ops->pre_root_reset_end)
|
||||||
* sunxi phy has a bug and it will wrongly detect high speed squelch
|
host->host->ops->pre_root_reset_end(host->host);
|
||||||
* when clearing reset on low-speed devices, temporary disable
|
|
||||||
* squelch detection to work around this.
|
|
||||||
*/
|
|
||||||
sunxi_usb_phy_enable_squelch_detect(0, 0);
|
|
||||||
#endif
|
|
||||||
power = musb_readb(mbase, MUSB_POWER);
|
power = musb_readb(mbase, MUSB_POWER);
|
||||||
musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
|
musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
|
||||||
#ifdef CONFIG_ARCH_SUNXI
|
|
||||||
sunxi_usb_phy_enable_squelch_detect(0, 1);
|
if (host->host->ops->post_root_reset_end)
|
||||||
#endif
|
host->host->ops->post_root_reset_end(host->host);
|
||||||
|
|
||||||
host->host->isr(0, host->host);
|
host->host->isr(0, host->host);
|
||||||
host->host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
|
host->host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
|
||||||
USB_SPEED_HIGH :
|
USB_SPEED_HIGH :
|
||||||
|
|
|
@ -304,10 +304,26 @@ static int sunxi_musb_init(struct musb *musb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sunxi_musb_pre_root_reset_end(struct musb *musb)
|
||||||
|
{
|
||||||
|
struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
|
||||||
|
|
||||||
|
sun4i_usb_phy_set_squelch_detect(glue->phy, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sunxi_musb_post_root_reset_end(struct musb *musb)
|
||||||
|
{
|
||||||
|
struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
|
||||||
|
|
||||||
|
sun4i_usb_phy_set_squelch_detect(glue->phy, true);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct musb_platform_ops sunxi_musb_ops = {
|
static const struct musb_platform_ops sunxi_musb_ops = {
|
||||||
.init = sunxi_musb_init,
|
.init = sunxi_musb_init,
|
||||||
.enable = sunxi_musb_enable,
|
.enable = sunxi_musb_enable,
|
||||||
.disable = sunxi_musb_disable,
|
.disable = sunxi_musb_disable,
|
||||||
|
.pre_root_reset_end = sunxi_musb_pre_root_reset_end,
|
||||||
|
.post_root_reset_end = sunxi_musb_post_root_reset_end,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Allwinner OTG supports up to 5 endpoints */
|
/* Allwinner OTG supports up to 5 endpoints */
|
||||||
|
|
|
@ -23,4 +23,12 @@ int sun4i_usb_phy_id_detect(struct phy *phy);
|
||||||
*/
|
*/
|
||||||
int sun4i_usb_phy_vbus_detect(struct phy *phy);
|
int sun4i_usb_phy_vbus_detect(struct phy *phy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sun4i_usb_phy_set_squelch_detect() - Enable/disable squelch detect
|
||||||
|
*
|
||||||
|
* @phy: reference to a sun4i usb phy
|
||||||
|
* @enabled: wether to enable or disable squelch detect
|
||||||
|
*/
|
||||||
|
void sun4i_usb_phy_set_squelch_detect(struct phy *phy, bool enabled);
|
||||||
|
|
||||||
#endif /*__GENERIC_PHY_SUN4I_USB_H */
|
#endif /*__GENERIC_PHY_SUN4I_USB_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue