blob: 360efc9116086f2b021bdfe1b471516a5a3fb104 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Roman Byshko637fbb62014-07-27 19:32:44 +02002/*
Hans de Goede86979092015-04-27 14:54:47 +02003 * Sunxi ehci glue
Roman Byshko637fbb62014-07-27 19:32:44 +02004 *
Hans de Goede86979092015-04-27 14:54:47 +02005 * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
6 * Copyright (C) 2014 Roman Byshko <rbyshko@gmail.com>
Roman Byshko637fbb62014-07-27 19:32:44 +02007 *
8 * Based on code from
9 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
Roman Byshko637fbb62014-07-27 19:32:44 +020010 */
11
Roman Byshko637fbb62014-07-27 19:32:44 +020012#include <common.h>
Hans de Goede7e5aabd2015-04-27 11:44:22 +020013#include <asm/arch/clock.h>
Hans de Goede7e5aabd2015-04-27 11:44:22 +020014#include <asm/io.h>
Hans de Goede4dba1082015-05-10 14:10:26 +020015#include <dm.h>
Roman Byshko637fbb62014-07-27 19:32:44 +020016#include "ehci.h"
Jagan Teki137fc752018-05-07 13:03:38 +053017#include <generic-phy.h>
Roman Byshko637fbb62014-07-27 19:32:44 +020018
Hans de Goede8b6ab7d2016-03-21 14:44:35 +010019#ifdef CONFIG_SUNXI_GEN_SUN4I
Hans de Goede8b6ab7d2016-03-21 14:44:35 +010020#define AHB_CLK_DIST 2
21#else
Hans de Goede8b6ab7d2016-03-21 14:44:35 +010022#define AHB_CLK_DIST 1
23#endif
24
Hans de Goede4dba1082015-05-10 14:10:26 +020025struct ehci_sunxi_priv {
26 struct ehci_ctrl ehci;
Jagan Tekifda15692018-05-07 13:03:17 +053027 struct sunxi_ccm_reg *ccm;
Hans de Goede4dba1082015-05-10 14:10:26 +020028 int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */
Jagan Teki137fc752018-05-07 13:03:38 +053029 struct phy phy;
Hans de Goede4dba1082015-05-10 14:10:26 +020030};
31
32static int ehci_usb_probe(struct udevice *dev)
Roman Byshko637fbb62014-07-27 19:32:44 +020033{
Hans de Goede4dba1082015-05-10 14:10:26 +020034 struct usb_platdata *plat = dev_get_platdata(dev);
35 struct ehci_sunxi_priv *priv = dev_get_priv(dev);
Simon Glassba1dea42017-05-17 17:18:05 -060036 struct ehci_hccr *hccr = (struct ehci_hccr *)devfdt_get_addr(dev);
Hans de Goede4dba1082015-05-10 14:10:26 +020037 struct ehci_hcor *hcor;
Hans de Goede52b5e5a2016-04-09 15:00:52 +020038 int extra_ahb_gate_mask = 0;
Jagan Teki137fc752018-05-07 13:03:38 +053039 int phys, ret;
Hans de Goede4dba1082015-05-10 14:10:26 +020040
Jagan Tekifda15692018-05-07 13:03:17 +053041 priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
42 if (IS_ERR(priv->ccm))
43 return PTR_ERR(priv->ccm);
44
Jagan Teki137fc752018-05-07 13:03:38 +053045 phys = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
46 if (phys < 0) {
47 phys = 0;
48 goto no_phy;
49 }
50
51 ret = generic_phy_get_by_name(dev, "usb", &priv->phy);
52 if (ret) {
53 pr_err("failed to get %s usb PHY\n", dev->name);
54 return ret;
55 }
56
57 ret = generic_phy_init(&priv->phy);
58 if (ret) {
59 pr_err("failed to init %s USB PHY\n", dev->name);
60 return ret;
61 }
62
63 ret = generic_phy_power_on(&priv->phy);
64 if (ret) {
65 pr_err("failed to power on %s USB PHY\n", dev->name);
66 return ret;
67 }
68
69no_phy:
Hans de Goede4dba1082015-05-10 14:10:26 +020070 /*
71 * This should go away once we've moved to the driver model for
72 * clocks resp. phys.
73 */
Jelle van der Waaa1f5d112016-02-09 23:59:33 +010074 priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0;
Andre Przywara5fb97432017-02-16 01:20:27 +000075#if defined(CONFIG_MACH_SUNXI_H3_H5) || defined(CONFIG_MACH_SUN50I)
Hans de Goede52b5e5a2016-04-09 15:00:52 +020076 extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0;
Jelle van der Waaa1f5d112016-02-09 23:59:33 +010077#endif
Jagan Teki137fc752018-05-07 13:03:38 +053078 priv->ahb_gate_mask <<= phys * AHB_CLK_DIST;
79 extra_ahb_gate_mask <<= phys * AHB_CLK_DIST;
Hans de Goedeaf4273b2014-11-07 16:09:00 +010080
Jagan Tekifda15692018-05-07 13:03:17 +053081 setbits_le32(&priv->ccm->ahb_gate0,
Hans de Goede52b5e5a2016-04-09 15:00:52 +020082 priv->ahb_gate_mask | extra_ahb_gate_mask);
Hans de Goede7e5aabd2015-04-27 11:44:22 +020083#ifdef CONFIG_SUNXI_GEN_SUN6I
Jagan Tekifda15692018-05-07 13:03:17 +053084 setbits_le32(&priv->ccm->ahb_reset0_cfg,
Hans de Goede52b5e5a2016-04-09 15:00:52 +020085 priv->ahb_gate_mask | extra_ahb_gate_mask);
Hans de Goede7e5aabd2015-04-27 11:44:22 +020086#endif
87
Amit Singh Tomarbd732d02016-10-21 02:24:30 +010088 hcor = (struct ehci_hcor *)((uintptr_t)hccr +
Hans de Goede4dba1082015-05-10 14:10:26 +020089 HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
Roman Byshko637fbb62014-07-27 19:32:44 +020090
Hans de Goede4dba1082015-05-10 14:10:26 +020091 return ehci_register(dev, hccr, hcor, NULL, 0, plat->init_type);
Roman Byshko637fbb62014-07-27 19:32:44 +020092}
93
Hans de Goede4dba1082015-05-10 14:10:26 +020094static int ehci_usb_remove(struct udevice *dev)
Roman Byshko637fbb62014-07-27 19:32:44 +020095{
Hans de Goede4dba1082015-05-10 14:10:26 +020096 struct ehci_sunxi_priv *priv = dev_get_priv(dev);
97 int ret;
98
Jagan Teki137fc752018-05-07 13:03:38 +053099 if (generic_phy_valid(&priv->phy)) {
100 ret = generic_phy_exit(&priv->phy);
101 if (ret) {
102 pr_err("failed to exit %s USB PHY\n", dev->name);
103 return ret;
104 }
105 }
106
Hans de Goede4dba1082015-05-10 14:10:26 +0200107 ret = ehci_deregister(dev);
108 if (ret)
109 return ret;
Hans de Goede7e5aabd2015-04-27 11:44:22 +0200110
Hans de Goede7e5aabd2015-04-27 11:44:22 +0200111#ifdef CONFIG_SUNXI_GEN_SUN6I
Jagan Tekifda15692018-05-07 13:03:17 +0530112 clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask);
Hans de Goede7e5aabd2015-04-27 11:44:22 +0200113#endif
Jagan Tekifda15692018-05-07 13:03:17 +0530114 clrbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask);
Hans de Goede7e5aabd2015-04-27 11:44:22 +0200115
Hans de Goede1168e092015-04-27 16:50:04 +0200116 return 0;
Roman Byshko637fbb62014-07-27 19:32:44 +0200117}
Hans de Goede4dba1082015-05-10 14:10:26 +0200118
119static const struct udevice_id ehci_usb_ids[] = {
120 { .compatible = "allwinner,sun4i-a10-ehci", },
121 { .compatible = "allwinner,sun5i-a13-ehci", },
122 { .compatible = "allwinner,sun6i-a31-ehci", },
123 { .compatible = "allwinner,sun7i-a20-ehci", },
124 { .compatible = "allwinner,sun8i-a23-ehci", },
Chen-Yu Tsaid0f38132016-03-30 00:26:53 +0800125 { .compatible = "allwinner,sun8i-a83t-ehci", },
Jelle van der Waaa1f5d112016-02-09 23:59:33 +0100126 { .compatible = "allwinner,sun8i-h3-ehci", },
Hans de Goede4dba1082015-05-10 14:10:26 +0200127 { .compatible = "allwinner,sun9i-a80-ehci", },
Amit Singh Tomarbd732d02016-10-21 02:24:30 +0100128 { .compatible = "allwinner,sun50i-a64-ehci", },
Hans de Goede4dba1082015-05-10 14:10:26 +0200129 { }
130};
131
Marek Vasutad693ce2015-11-30 18:15:33 +0100132U_BOOT_DRIVER(ehci_sunxi) = {
Hans de Goede4dba1082015-05-10 14:10:26 +0200133 .name = "ehci_sunxi",
134 .id = UCLASS_USB,
135 .of_match = ehci_usb_ids,
136 .probe = ehci_usb_probe,
137 .remove = ehci_usb_remove,
138 .ops = &ehci_usb_ops,
139 .platdata_auto_alloc_size = sizeof(struct usb_platdata),
140 .priv_auto_alloc_size = sizeof(struct ehci_sunxi_priv),
141 .flags = DM_FLAG_ALLOC_PRIV_DMA,
142};