blob: 622d7b9cf4f9a081fb848051baaeb96d0d9b8b4c [file] [log] [blame]
Paul Barkerc8196982025-03-11 20:57:43 +00001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2024 Renesas Electronics Corporation
4 */
5
6#include <asm/io.h>
7#include <dm.h>
Paul Barkerced6d032025-03-11 20:57:45 +00008#include <dm/device-internal.h>
Paul Barkerc8196982025-03-11 20:57:43 +00009#include <dm/device_compat.h>
10#include <dm/lists.h>
11#include <renesas/rzg2l-usbphy.h>
12#include <reset-uclass.h>
13#include <reset.h>
14
15#define RESET 0x000
16
17#define RESET_SEL_PLLRESET BIT(12)
18#define RESET_PLLRESET BIT(8)
19
20#define RESET_SEL_P2RESET BIT(5)
21#define RESET_SEL_P1RESET BIT(4)
22#define RESET_PHYRST_2 BIT(1)
23#define RESET_PHYRST_1 BIT(0)
24
25#define PHY_RESET_MASK (RESET_PHYRST_1 | RESET_PHYRST_2)
26
27#define NUM_PORTS 2
28
29static int rzg2l_usbphy_ctrl_assert(struct reset_ctl *reset_ctl)
30{
31 struct rzg2l_usbphy_ctrl_priv *priv = dev_get_priv(reset_ctl->dev);
32 u32 val;
33
34 val = readl(priv->regs + RESET);
35 val |= reset_ctl->id ? RESET_PHYRST_2 : RESET_PHYRST_1;
36
37 /* If both ports are in reset, we can also place the PLL into reset. */
38 if ((val & PHY_RESET_MASK) == PHY_RESET_MASK)
39 val |= RESET_PLLRESET;
40
41 writel(val, priv->regs + RESET);
42 return 0;
43}
44
45static int rzg2l_usbphy_ctrl_deassert(struct reset_ctl *reset_ctl)
46{
47 struct rzg2l_usbphy_ctrl_priv *priv = dev_get_priv(reset_ctl->dev);
48 u32 val = reset_ctl->id ? RESET_PHYRST_2 : RESET_PHYRST_1;
49
50 /* If either port is out of reset, the PLL must also be out of reset. */
51 val |= RESET_PLLRESET;
52
53 clrbits_le32(priv->regs + RESET, val);
54 return 0;
55}
56
57static int rzg2l_usbphy_ctrl_of_xlate(struct reset_ctl *reset_ctl,
58 struct ofnode_phandle_args *args)
59{
60 if (args->args[0] >= NUM_PORTS)
61 return -EINVAL;
62
63 reset_ctl->id = args->args[0];
64 return 0;
65}
66
67struct reset_ops rzg2l_usbphy_ctrl_ops = {
68 .rst_assert = rzg2l_usbphy_ctrl_assert,
69 .rst_deassert = rzg2l_usbphy_ctrl_deassert,
70 .of_xlate = rzg2l_usbphy_ctrl_of_xlate,
71};
72
73static int rzg2l_usbphy_ctrl_probe(struct udevice *dev)
74{
75 struct rzg2l_usbphy_ctrl_priv *priv = dev_get_priv(dev);
76 struct reset_ctl rst;
77 int ret;
78
79 priv->regs = dev_read_addr(dev);
80
81 ret = reset_get_by_index(dev, 0, &rst);
82 if (ret < 0) {
83 dev_err(dev, "failed to get reset line: %d\n", ret);
84 return ret;
85 }
86
87 ret = reset_deassert(&rst);
88 if (ret < 0) {
89 dev_err(dev, "failed to de-assert reset line: %d\n", ret);
90 return ret;
91 }
92
93 /* put pll and phy into reset state */
94 setbits_le32(priv->regs + RESET,
95 RESET_SEL_PLLRESET | RESET_PLLRESET |
96 RESET_SEL_P1RESET | RESET_PHYRST_1 |
97 RESET_SEL_P2RESET | RESET_PHYRST_2);
98
99 return 0;
100}
101
102static const struct udevice_id rzg2l_usbphy_ctrl_ids[] = {
103 { .compatible = "renesas,rzg2l-usbphy-ctrl", },
104 { /* sentinel */ }
105};
106
Paul Barkerced6d032025-03-11 20:57:45 +0000107static int rzg2l_usbphy_ctrl_bind(struct udevice *dev)
108{
109 struct driver *drv;
110 ofnode node;
111 int ret;
112
113 node = ofnode_find_subnode(dev_ofnode(dev), "regulator-vbus");
114 if (!ofnode_valid(node)) {
115 dev_err(dev, "Failed to find vbus regulator devicetree node\n");
116 return -ENOENT;
117 }
118
119 drv = lists_driver_lookup_name("rzg2l_usbphy_regulator");
120 if (!drv) {
121 dev_err(dev, "Failed to find vbus regulator driver\n");
122 return -ENOENT;
123 }
124
125 ret = device_bind(dev, drv, dev->name, NULL, node, NULL);
126 if (ret) {
127 dev_err(dev, "Failed to bind vbus regulator: %d\n", ret);
128 return ret;
129 }
130
131 return 0;
132}
133
Paul Barkerc8196982025-03-11 20:57:43 +0000134U_BOOT_DRIVER(rzg2l_usbphy_ctrl) = {
135 .name = "rzg2l_usbphy_ctrl",
136 .id = UCLASS_RESET,
137 .of_match = rzg2l_usbphy_ctrl_ids,
Paul Barkerced6d032025-03-11 20:57:45 +0000138 .bind = rzg2l_usbphy_ctrl_bind,
Paul Barkerc8196982025-03-11 20:57:43 +0000139 .probe = rzg2l_usbphy_ctrl_probe,
140 .ops = &rzg2l_usbphy_ctrl_ops,
141 .priv_auto = sizeof(struct rzg2l_usbphy_ctrl_priv),
142};