diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/ehci-sunxi.c | 98 | ||||
-rw-r--r-- | drivers/usb/host/ohci-sunxi.c | 109 |
2 files changed, 166 insertions, 41 deletions
diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 360efc9116..97d06d5975 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -22,11 +22,22 @@ #define AHB_CLK_DIST 1 #endif +#define SUN6I_AHB_RESET0_CFG_OFFSET 0x2c0 +#define SUN9I_AHB_RESET0_CFG_OFFSET 0x5a0 + +struct ehci_sunxi_cfg { + bool has_reset; + u32 extra_ahb_gate_mask; + u32 reset0_cfg_offset; +}; + struct ehci_sunxi_priv { struct ehci_ctrl ehci; struct sunxi_ccm_reg *ccm; + u32 *reset0_cfg; int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */ struct phy phy; + const struct ehci_sunxi_cfg *cfg; }; static int ehci_usb_probe(struct udevice *dev) @@ -38,10 +49,14 @@ static int ehci_usb_probe(struct udevice *dev) int extra_ahb_gate_mask = 0; int phys, ret; + priv->cfg = (const struct ehci_sunxi_cfg *)dev_get_driver_data(dev); priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; if (IS_ERR(priv->ccm)) return PTR_ERR(priv->ccm); + priv->reset0_cfg = (void *)priv->ccm + + priv->cfg->reset0_cfg_offset; + phys = dev_count_phandle_with_args(dev, "phys", "#phy-cells"); if (phys < 0) { phys = 0; @@ -72,18 +87,15 @@ no_phy: * clocks resp. phys. */ priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0; -#if defined(CONFIG_MACH_SUNXI_H3_H5) || defined(CONFIG_MACH_SUN50I) - extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0; -#endif + extra_ahb_gate_mask = priv->cfg->extra_ahb_gate_mask; priv->ahb_gate_mask <<= phys * AHB_CLK_DIST; extra_ahb_gate_mask <<= phys * AHB_CLK_DIST; setbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask | extra_ahb_gate_mask); -#ifdef CONFIG_SUNXI_GEN_SUN6I - setbits_le32(&priv->ccm->ahb_reset0_cfg, - priv->ahb_gate_mask | extra_ahb_gate_mask); -#endif + if (priv->cfg->has_reset) + setbits_le32(priv->reset0_cfg, + priv->ahb_gate_mask | extra_ahb_gate_mask); hcor = (struct ehci_hcor *)((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); @@ -108,25 +120,71 @@ static int ehci_usb_remove(struct udevice *dev) if (ret) return ret; -#ifdef CONFIG_SUNXI_GEN_SUN6I - clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask); -#endif + if (priv->cfg->has_reset) + clrbits_le32(priv->reset0_cfg, priv->ahb_gate_mask); clrbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask); return 0; } +static const struct ehci_sunxi_cfg sun4i_a10_cfg = { + .has_reset = false, +}; + +static const struct ehci_sunxi_cfg sun6i_a31_cfg = { + .has_reset = true, + .reset0_cfg_offset = SUN6I_AHB_RESET0_CFG_OFFSET, +}; + +static const struct ehci_sunxi_cfg sun8i_h3_cfg = { + .has_reset = true, + .extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0, + .reset0_cfg_offset = SUN6I_AHB_RESET0_CFG_OFFSET, +}; + +static const struct ehci_sunxi_cfg sun9i_a80_cfg = { + .has_reset = true, + .reset0_cfg_offset = SUN9I_AHB_RESET0_CFG_OFFSET, +}; + static const struct udevice_id ehci_usb_ids[] = { - { .compatible = "allwinner,sun4i-a10-ehci", }, - { .compatible = "allwinner,sun5i-a13-ehci", }, - { .compatible = "allwinner,sun6i-a31-ehci", }, - { .compatible = "allwinner,sun7i-a20-ehci", }, - { .compatible = "allwinner,sun8i-a23-ehci", }, - { .compatible = "allwinner,sun8i-a83t-ehci", }, - { .compatible = "allwinner,sun8i-h3-ehci", }, - { .compatible = "allwinner,sun9i-a80-ehci", }, - { .compatible = "allwinner,sun50i-a64-ehci", }, - { } + { + .compatible = "allwinner,sun4i-a10-ehci", + .data = (ulong)&sun4i_a10_cfg, + }, + { + .compatible = "allwinner,sun5i-a13-ehci", + .data = (ulong)&sun4i_a10_cfg, + }, + { + .compatible = "allwinner,sun6i-a31-ehci", + .data = (ulong)&sun6i_a31_cfg, + }, + { + .compatible = "allwinner,sun7i-a20-ehci", + .data = (ulong)&sun4i_a10_cfg, + }, + { + .compatible = "allwinner,sun8i-a23-ehci", + .data = (ulong)&sun6i_a31_cfg, + }, + { + .compatible = "allwinner,sun8i-a83t-ehci", + .data = (ulong)&sun6i_a31_cfg, + }, + { + .compatible = "allwinner,sun8i-h3-ehci", + .data = (ulong)&sun8i_h3_cfg, + }, + { + .compatible = "allwinner,sun9i-a80-ehci", + .data = (ulong)&sun9i_a80_cfg, + }, + { + .compatible = "allwinner,sun50i-a64-ehci", + .data = (ulong)&sun8i_h3_cfg, + }, + { /* sentinel */ } }; U_BOOT_DRIVER(ehci_sunxi) = { diff --git a/drivers/usb/host/ohci-sunxi.c b/drivers/usb/host/ohci-sunxi.c index ce2b47a5c4..e13f6ec9a4 100644 --- a/drivers/usb/host/ohci-sunxi.c +++ b/drivers/usb/host/ohci-sunxi.c @@ -22,12 +22,24 @@ #define AHB_CLK_DIST 1 #endif +#define SUN6I_AHB_RESET0_CFG_OFFSET 0x2c0 +#define SUN9I_AHB_RESET0_CFG_OFFSET 0x5a0 + +struct ohci_sunxi_cfg { + bool has_reset; + u32 extra_ahb_gate_mask; + u32 extra_usb_gate_mask; + u32 reset0_cfg_offset; +}; + struct ohci_sunxi_priv { struct sunxi_ccm_reg *ccm; + u32 *reset0_cfg; ohci_t ohci; int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */ int usb_gate_mask; /* Mask of usb_clk_cfg clk gate bits for this hcd */ struct phy phy; + const struct ohci_sunxi_cfg *cfg; }; static int ohci_usb_probe(struct udevice *dev) @@ -38,10 +50,14 @@ static int ohci_usb_probe(struct udevice *dev) int extra_ahb_gate_mask = 0; int phys, ret; + priv->cfg = (const struct ohci_sunxi_cfg *)dev_get_driver_data(dev); priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; if (IS_ERR(priv->ccm)) return PTR_ERR(priv->ccm); + priv->reset0_cfg = (void *)priv->ccm + + priv->cfg->reset0_cfg_offset; + phys = dev_count_phandle_with_args(dev, "phys", "#phy-cells"); if (phys < 0) { phys = 0; @@ -74,9 +90,7 @@ no_phy: * clocks resp. phys. */ priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0; -#ifdef CONFIG_MACH_SUN8I_H3 - extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0; -#endif + extra_ahb_gate_mask = priv->cfg->extra_ahb_gate_mask; priv->usb_gate_mask = CCM_USB_CTRL_OHCI0_CLK; priv->ahb_gate_mask <<= phys * AHB_CLK_DIST; extra_ahb_gate_mask <<= phys * AHB_CLK_DIST; @@ -84,11 +98,11 @@ no_phy: setbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask | extra_ahb_gate_mask); - setbits_le32(&priv->ccm->usb_clk_cfg, priv->usb_gate_mask); -#ifdef CONFIG_SUNXI_GEN_SUN6I - setbits_le32(&priv->ccm->ahb_reset0_cfg, - priv->ahb_gate_mask | extra_ahb_gate_mask); -#endif + setbits_le32(&priv->ccm->usb_clk_cfg, + priv->usb_gate_mask | priv->cfg->extra_usb_gate_mask); + if (priv->cfg->has_reset) + setbits_le32(priv->reset0_cfg, + priv->ahb_gate_mask | extra_ahb_gate_mask); return ohci_register(dev, regs); } @@ -110,26 +124,79 @@ static int ohci_usb_remove(struct udevice *dev) if (ret) return ret; -#ifdef CONFIG_SUNXI_GEN_SUN6I - clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask); -#endif + if (priv->cfg->has_reset) + clrbits_le32(priv->reset0_cfg, priv->ahb_gate_mask); clrbits_le32(&priv->ccm->usb_clk_cfg, priv->usb_gate_mask); clrbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask); return 0; } +static const struct ohci_sunxi_cfg sun4i_a10_cfg = { + .has_reset = false, +}; + +static const struct ohci_sunxi_cfg sun6i_a31_cfg = { + .has_reset = true, + .reset0_cfg_offset = SUN6I_AHB_RESET0_CFG_OFFSET, +}; + +static const struct ohci_sunxi_cfg sun8i_h3_cfg = { + .has_reset = true, + .extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0, + .reset0_cfg_offset = SUN6I_AHB_RESET0_CFG_OFFSET, +}; + +static const struct ohci_sunxi_cfg sun9i_a80_cfg = { + .has_reset = true, + .reset0_cfg_offset = SUN9I_AHB_RESET0_CFG_OFFSET, +}; + +static const struct ohci_sunxi_cfg sun50i_a64_cfg = { + .has_reset = true, + .extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0, + .extra_usb_gate_mask = CCM_USB_CTRL_OHCI0_CLK, + .reset0_cfg_offset = SUN6I_AHB_RESET0_CFG_OFFSET, +}; + static const struct udevice_id ohci_usb_ids[] = { - { .compatible = "allwinner,sun4i-a10-ohci", }, - { .compatible = "allwinner,sun5i-a13-ohci", }, - { .compatible = "allwinner,sun6i-a31-ohci", }, - { .compatible = "allwinner,sun7i-a20-ohci", }, - { .compatible = "allwinner,sun8i-a23-ohci", }, - { .compatible = "allwinner,sun8i-a83t-ohci", }, - { .compatible = "allwinner,sun8i-h3-ohci", }, - { .compatible = "allwinner,sun9i-a80-ohci", }, - { .compatible = "allwinner,sun50i-a64-ohci", }, - { } + { + .compatible = "allwinner,sun4i-a10-ohci", + .data = (ulong)&sun4i_a10_cfg, + }, + { + .compatible = "allwinner,sun5i-a13-ohci", + .data = (ulong)&sun4i_a10_cfg, + }, + { + .compatible = "allwinner,sun6i-a31-ohci", + .data = (ulong)&sun6i_a31_cfg, + }, + { + .compatible = "allwinner,sun7i-a20-ohci", + .data = (ulong)&sun4i_a10_cfg, + }, + { + .compatible = "allwinner,sun8i-a23-ohci", + .data = (ulong)&sun6i_a31_cfg, + }, + { + .compatible = "allwinner,sun8i-a83t-ohci", + .data = (ulong)&sun6i_a31_cfg, + }, + { + .compatible = "allwinner,sun8i-h3-ohci", + .data = (ulong)&sun8i_h3_cfg, + }, + { + .compatible = "allwinner,sun9i-a80-ohci", + .data = (ulong)&sun9i_a80_cfg, + }, + { + .compatible = "allwinner,sun50i-a64-ohci", + .data = (ulong)&sun50i_a64_cfg, + }, + { /* sentinel */ } }; U_BOOT_DRIVER(usb_ohci) = { |