mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +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_SLEWRATE_TUNE 0x22
|
||||
#define PHY_DISCON_TH_SEL 0x2a
|
||||
#define PHY_SQUELCH_DETECT 0x3c
|
||||
|
||||
#define PHYCTL_DATA BIT(7)
|
||||
#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);
|
||||
}
|
||||
|
||||
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 = {
|
||||
.of_xlate = sun4i_usb_phy_xlate,
|
||||
.init = sun4i_usb_phy_init,
|
||||
|
|
|
@ -200,6 +200,8 @@ enum musb_g_ep0_state {
|
|||
* @vbus_status: returns vbus status if possible
|
||||
* @set_vbus: forces vbus status
|
||||
* @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 {
|
||||
int (*init)(struct musb *musb);
|
||||
|
@ -221,6 +223,8 @@ struct musb_platform_ops {
|
|||
int (*adjust_channel_params)(struct dma_channel *channel,
|
||||
u16 packet_sz, u8 *mode,
|
||||
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;
|
||||
musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
|
||||
mdelay(50);
|
||||
#ifdef CONFIG_ARCH_SUNXI
|
||||
/*
|
||||
* sunxi phy has a bug and it will wrongly detect high speed squelch
|
||||
* when clearing reset on low-speed devices, temporary disable
|
||||
* squelch detection to work around this.
|
||||
*/
|
||||
sunxi_usb_phy_enable_squelch_detect(0, 0);
|
||||
#endif
|
||||
|
||||
if (host->host->ops->pre_root_reset_end)
|
||||
host->host->ops->pre_root_reset_end(host->host);
|
||||
|
||||
power = musb_readb(mbase, MUSB_POWER);
|
||||
musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
|
||||
#ifdef CONFIG_ARCH_SUNXI
|
||||
sunxi_usb_phy_enable_squelch_detect(0, 1);
|
||||
#endif
|
||||
|
||||
if (host->host->ops->post_root_reset_end)
|
||||
host->host->ops->post_root_reset_end(host->host);
|
||||
|
||||
host->host->isr(0, host->host);
|
||||
host->host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
|
||||
USB_SPEED_HIGH :
|
||||
|
|
|
@ -304,10 +304,26 @@ static int sunxi_musb_init(struct musb *musb)
|
|||
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 = {
|
||||
.init = sunxi_musb_init,
|
||||
.enable = sunxi_musb_enable,
|
||||
.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 */
|
||||
|
|
|
@ -23,4 +23,12 @@ int sun4i_usb_phy_id_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 */
|
||||
|
|
Loading…
Reference in a new issue