blob: 23c3ed25554f9acfeac840a132d99b92e3b8fafa [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Alexey Brodkina6aff432015-12-02 12:32:02 +03002/*
3 * Copyright (C) 2015 Alexey Brodkin <abrodkin@synopsys.com>
Alexey Brodkina6aff432015-12-02 12:32:02 +03004 */
5
Masahiro Yamadafbb66bf2016-01-25 15:00:36 +09006#include <clk.h>
Simon Glass0f2af882020-05-10 11:40:05 -06007#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -07008#include <dm/device_compat.h>
Simon Glassd66c5f72020-02-03 07:36:15 -07009#include <dm/devres.h>
Patrice Chotarda0809dc2017-07-18 11:57:10 +020010#include <dm/ofnode.h>
Patrice Chotard1a62cde2017-07-18 11:57:11 +020011#include <generic-phy.h>
Masahiro Yamada8a5a1802016-09-21 11:29:02 +090012#include <reset.h>
Marek Vasut851fecc2016-01-23 21:04:46 +010013#include <asm/io.h>
Alexey Brodkina6aff432015-12-02 12:32:02 +030014#include <dm.h>
15#include "ehci.h"
Patrice Chotardfc424682018-09-04 11:37:25 +020016#include <power/regulator.h>
Alexey Brodkina6aff432015-12-02 12:32:02 +030017
18/*
19 * Even though here we don't explicitly use "struct ehci_ctrl"
20 * ehci_register() expects it to be the first thing that resides in
21 * device's private data.
22 */
23struct generic_ehci {
24 struct ehci_ctrl ctrl;
Patrice Chotard0ef45712022-05-06 08:22:34 +020025 struct clk_bulk clocks;
26 struct reset_ctl_bulk resets;
Patrice Chotard1a62cde2017-07-18 11:57:11 +020027 struct phy phy;
Patrice Chotardfc424682018-09-04 11:37:25 +020028 struct udevice *vbus_supply;
Alexey Brodkina6aff432015-12-02 12:32:02 +030029};
30
Patrice Chotardfc424682018-09-04 11:37:25 +020031static int ehci_enable_vbus_supply(struct udevice *dev)
32{
33 struct generic_ehci *priv = dev_get_priv(dev);
34 int ret;
35
36 ret = device_get_supply_regulator(dev, "vbus-supply",
37 &priv->vbus_supply);
38 if (ret && ret != -ENOENT)
39 return ret;
40
Jonas Karlman2b9e2482023-07-19 21:20:57 +000041 ret = regulator_set_enable_if_allowed(priv->vbus_supply, true);
42 if (ret && ret != -ENOSYS) {
43 dev_err(dev, "Error enabling VBUS supply (ret=%d)\n", ret);
44 return ret;
Patrice Chotardfc424682018-09-04 11:37:25 +020045 }
46
47 return 0;
48}
49
50static int ehci_disable_vbus_supply(struct generic_ehci *priv)
51{
Jonas Karlman2b9e2482023-07-19 21:20:57 +000052 int ret;
53
54 ret = regulator_set_enable_if_allowed(priv->vbus_supply, false);
55 if (ret && ret != -ENOSYS)
56 return ret;
57
58 return 0;
Patrice Chotardfc424682018-09-04 11:37:25 +020059}
Patrice Chotardfc424682018-09-04 11:37:25 +020060
Alexey Brodkina6aff432015-12-02 12:32:02 +030061static int ehci_usb_probe(struct udevice *dev)
62{
Patrice Chotarda0809dc2017-07-18 11:57:10 +020063 struct generic_ehci *priv = dev_get_priv(dev);
Marek Vasut851fecc2016-01-23 21:04:46 +010064 struct ehci_hccr *hccr;
Alexey Brodkina6aff432015-12-02 12:32:02 +030065 struct ehci_hcor *hcor;
Patrice Chotard0ef45712022-05-06 08:22:34 +020066 int err, ret;
Masahiro Yamadafbb66bf2016-01-25 15:00:36 +090067
Patrice Chotarda0809dc2017-07-18 11:57:10 +020068 err = 0;
Patrice Chotard0ef45712022-05-06 08:22:34 +020069 ret = clk_get_bulk(dev, &priv->clocks);
Andre Przywarafbcb8f02022-06-08 00:42:22 +010070 if (ret && ret != -ENOENT) {
Patrice Chotard0ef45712022-05-06 08:22:34 +020071 dev_err(dev, "Failed to get clocks (ret=%d)\n", ret);
72 return ret;
Masahiro Yamadafbb66bf2016-01-25 15:00:36 +090073 }
Alexey Brodkina6aff432015-12-02 12:32:02 +030074
Patrice Chotard0ef45712022-05-06 08:22:34 +020075 err = clk_enable_bulk(&priv->clocks);
76 if (err) {
77 dev_err(dev, "Failed to enable clocks (err=%d)\n", err);
78 goto clk_err;
79 }
Masahiro Yamada8a5a1802016-09-21 11:29:02 +090080
Patrice Chotard0ef45712022-05-06 08:22:34 +020081 err = reset_get_bulk(dev, &priv->resets);
Andre Przywara47bb0dc2022-07-02 01:45:10 +010082 if (err && err != -ENOENT) {
Patrice Chotard0ef45712022-05-06 08:22:34 +020083 dev_err(dev, "Failed to get resets (err=%d)\n", err);
84 goto clk_err;
85 }
Patrice Chotarda0809dc2017-07-18 11:57:10 +020086
Patrice Chotard0ef45712022-05-06 08:22:34 +020087 err = reset_deassert_bulk(&priv->resets);
88 if (err) {
89 dev_err(dev, "Failed to get deassert resets (err=%d)\n", err);
90 goto reset_err;
Masahiro Yamada8a5a1802016-09-21 11:29:02 +090091 }
92
Patrice Chotardfc424682018-09-04 11:37:25 +020093 err = ehci_enable_vbus_supply(dev);
Patrice Chotard36afc032018-03-14 17:48:54 +010094 if (err)
Patrice Chotard36afc032018-03-14 17:48:54 +010095 goto reset_err;
Patrice Chotard1a62cde2017-07-18 11:57:11 +020096
Patrice Chotard343ff752022-09-06 08:15:28 +020097 err = generic_setup_phy(dev, &priv->phy, 0);
Patrice Chotardfc424682018-09-04 11:37:25 +020098 if (err)
99 goto regulator_err;
100
Philipp Tomsich9f3f4232017-09-12 17:32:28 +0200101 hccr = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE);
Alexey Brodkina6aff432015-12-02 12:32:02 +0300102 hcor = (struct ehci_hcor *)((uintptr_t)hccr +
103 HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
104
Patrice Chotarda0809dc2017-07-18 11:57:10 +0200105 err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
106 if (err)
Patrice Chotard1a62cde2017-07-18 11:57:11 +0200107 goto phy_err;
Patrice Chotarda0809dc2017-07-18 11:57:10 +0200108
109 return 0;
110
Patrice Chotard1a62cde2017-07-18 11:57:11 +0200111phy_err:
Patrice Chotard343ff752022-09-06 08:15:28 +0200112 ret = generic_shutdown_phy(&priv->phy);
Patrice Chotard36afc032018-03-14 17:48:54 +0100113 if (ret)
Patrice Chotard0ef45712022-05-06 08:22:34 +0200114 dev_err(dev, "failed to shutdown usb phy (ret=%d)\n", ret);
Patrice Chotard1a62cde2017-07-18 11:57:11 +0200115
Patrice Chotardfc424682018-09-04 11:37:25 +0200116regulator_err:
117 ret = ehci_disable_vbus_supply(priv);
118 if (ret)
Patrice Chotard0ef45712022-05-06 08:22:34 +0200119 dev_err(dev, "failed to disable VBUS supply (ret=%d)\n", ret);
Patrice Chotardfc424682018-09-04 11:37:25 +0200120
Patrice Chotarda0809dc2017-07-18 11:57:10 +0200121reset_err:
Patrice Chotard0ef45712022-05-06 08:22:34 +0200122 ret = reset_release_bulk(&priv->resets);
Patrice Chotarda0809dc2017-07-18 11:57:10 +0200123 if (ret)
Patrice Chotard0ef45712022-05-06 08:22:34 +0200124 dev_err(dev, "failed to release resets (ret=%d)\n", ret);
Patrice Chotarda0809dc2017-07-18 11:57:10 +0200125clk_err:
Patrice Chotard0ef45712022-05-06 08:22:34 +0200126 ret = clk_release_bulk(&priv->clocks);
Patrice Chotarda0809dc2017-07-18 11:57:10 +0200127 if (ret)
Patrice Chotard0ef45712022-05-06 08:22:34 +0200128 dev_err(dev, "failed to release clocks (ret=%d)\n", ret);
Patrice Chotarda0809dc2017-07-18 11:57:10 +0200129
130 return err;
131}
132
133static int ehci_usb_remove(struct udevice *dev)
134{
135 struct generic_ehci *priv = dev_get_priv(dev);
136 int ret;
137
138 ret = ehci_deregister(dev);
139 if (ret)
140 return ret;
141
Patrice Chotard343ff752022-09-06 08:15:28 +0200142 ret = generic_shutdown_phy(&priv->phy);
Patrice Chotard36afc032018-03-14 17:48:54 +0100143 if (ret)
144 return ret;
Patrice Chotard1a62cde2017-07-18 11:57:11 +0200145
Patrice Chotardfc424682018-09-04 11:37:25 +0200146 ret = ehci_disable_vbus_supply(priv);
147 if (ret)
148 return ret;
149
Patrice Chotard0ef45712022-05-06 08:22:34 +0200150 ret = reset_release_bulk(&priv->resets);
Patrice Chotarda0809dc2017-07-18 11:57:10 +0200151 if (ret)
152 return ret;
153
Patrice Chotard0ef45712022-05-06 08:22:34 +0200154 return clk_release_bulk(&priv->clocks);
Alexey Brodkina6aff432015-12-02 12:32:02 +0300155}
156
Alexey Brodkina6aff432015-12-02 12:32:02 +0300157static const struct udevice_id ehci_usb_ids[] = {
158 { .compatible = "generic-ehci" },
159 { }
160};
161
162U_BOOT_DRIVER(ehci_generic) = {
163 .name = "ehci_generic",
164 .id = UCLASS_USB,
165 .of_match = ehci_usb_ids,
166 .probe = ehci_usb_probe,
Patrice Chotarda0809dc2017-07-18 11:57:10 +0200167 .remove = ehci_usb_remove,
Alexey Brodkina6aff432015-12-02 12:32:02 +0300168 .ops = &ehci_usb_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700169 .priv_auto = sizeof(struct generic_ehci),
Alexey Brodkina6aff432015-12-02 12:32:02 +0300170 .flags = DM_FLAG_ALLOC_PRIV_DMA,
171};