X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fusb%2Fmusb-new%2Fsunxi.c;h=c123d61af2c3d274b76d7395b9e4460b257624ec;hb=3c9cc70d7153da442575112d9a2643eecd17d534;hp=778916df00b76a56d2bb257a45f53e4b1eedfe5d;hpb=ade8bc14ad419f698406b162c9c5dfeee7406b4c;p=oweals%2Fu-boot.git diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 778916df00..c123d61af2 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -22,9 +22,21 @@ */ #include #include -#include +#include +#include +#include +#include #include "linux-compat.h" #include "musb_core.h" +#ifdef CONFIG_AXP152_POWER +#include +#endif +#ifdef CONFIG_AXP209_POWER +#include +#endif +#ifdef CONFIG_AXP221_POWER +#include +#endif /****************************************************************************** ****************************************************************************** @@ -93,16 +105,6 @@ static void USBC_EnableIdPullUp(__iomem void *base) musb_writel(base, USBC_REG_o_ISCR, reg_val); } -static void USBC_DisableIdPullUp(__iomem void *base) -{ - u32 reg_val; - - reg_val = musb_readl(base, USBC_REG_o_ISCR); - reg_val &= ~(1 << USBC_BP_ISCR_ID_PULLUP_EN); - reg_val = USBC_WakeUp_ClearChangeDetect(reg_val); - musb_writel(base, USBC_REG_o_ISCR, reg_val); -} - static void USBC_EnableDpDmPullUp(__iomem void *base) { u32 reg_val; @@ -113,16 +115,6 @@ static void USBC_EnableDpDmPullUp(__iomem void *base) musb_writel(base, USBC_REG_o_ISCR, reg_val); } -static void USBC_DisableDpDmPullUp(__iomem void *base) -{ - u32 reg_val; - - reg_val = musb_readl(base, USBC_REG_o_ISCR); - reg_val &= ~(1 << USBC_BP_ISCR_DPDM_PULLUP_EN); - reg_val = USBC_WakeUp_ClearChangeDetect(reg_val); - musb_writel(base, USBC_REG_o_ISCR, reg_val); -} - static void USBC_ForceIdToLow(__iomem void *base) { u32 reg_val; @@ -145,12 +137,13 @@ static void USBC_ForceIdToHigh(__iomem void *base) musb_writel(base, USBC_REG_o_ISCR, reg_val); } -static void USBC_ForceVbusValidDisable(__iomem void *base) +static void USBC_ForceVbusValidToLow(__iomem void *base) { u32 reg_val; reg_val = musb_readl(base, USBC_REG_o_ISCR); reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID); + reg_val |= (0x02 << USBC_BP_ISCR_FORCE_VBUS_VALID); reg_val = USBC_WakeUp_ClearChangeDetect(reg_val); musb_writel(base, USBC_REG_o_ISCR, reg_val); } @@ -203,43 +196,66 @@ static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci) return retval; } -static void sunxi_musb_enable(struct musb *musb) +/* musb_core does not call enable / disable in a balanced manner */ +static bool enabled = false; + +static int sunxi_musb_enable(struct musb *musb) { pr_debug("%s():\n", __func__); + if (enabled) + return 0; + /* select PIO mode */ musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0); - if (is_host_enabled(musb)) { - /* port power on */ - sunxi_usbc_vbus_enable(0); - } + if (is_host_enabled(musb)) + sunxi_usb_phy_power_on(0); /* port power on */ + + USBC_ForceVbusValidToHigh(musb->mregs); + + enabled = true; + return 0; } static void sunxi_musb_disable(struct musb *musb) { pr_debug("%s():\n", __func__); - /* Put the controller back in a pristane state for "usb reset" */ - if (musb->is_active) { - sunxi_usbc_disable(0); - sunxi_usbc_enable(0); - musb->is_active = 0; - } + if (!enabled) + return; + + if (is_host_enabled(musb)) + sunxi_usb_phy_power_off(0); /* port power off */ + + USBC_ForceVbusValidToLow(musb->mregs); + mdelay(200); /* Wait for the current session to timeout */ + + enabled = false; } static int sunxi_musb_init(struct musb *musb) { + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; int err; pr_debug("%s():\n", __func__); - err = sunxi_usbc_request_resources(0); - if (err) - return err; + if (is_host_enabled(musb)) { + err = sunxi_usb_phy_vbus_detect(0); + if (err) { + eprintf("Error: A charger is plugged into the OTG\n"); + return -EIO; + } + } musb->isr = sunxi_musb_interrupt; - sunxi_usbc_enable(0); + + setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); +#ifdef CONFIG_SUNXI_GEN_SUN6I + setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); +#endif + sunxi_usb_phy_init(0); USBC_ConfigFIFO_Base(); USBC_EnableDpDmPullUp(musb->mregs); @@ -248,32 +264,17 @@ static int sunxi_musb_init(struct musb *musb) if (is_host_enabled(musb)) { /* Host mode */ USBC_ForceIdToLow(musb->mregs); - USBC_ForceVbusValidToHigh(musb->mregs); } else { /* Peripheral mode */ USBC_ForceIdToHigh(musb->mregs); - USBC_ForceVbusValidDisable(musb->mregs); } + USBC_ForceVbusValidToHigh(musb->mregs); return 0; } -static int sunxi_musb_exit(struct musb *musb) -{ - pr_debug("%s():\n", __func__); - - USBC_DisableDpDmPullUp(musb->mregs); - USBC_DisableIdPullUp(musb->mregs); - sunxi_usbc_vbus_disable(0); - sunxi_usbc_disable(0); - - return sunxi_usbc_free_resources(0); -} - const struct musb_platform_ops sunxi_musb_ops = { .init = sunxi_musb_init, - .exit = sunxi_musb_exit, - .enable = sunxi_musb_enable, .disable = sunxi_musb_disable, };