blob: afd647e00b19d6eb119914bda11e3343fbca38f6 [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>
8#include <dm/device_compat.h>
9#include <dm/lists.h>
10#include <renesas/rzg2l-usbphy.h>
11#include <reset-uclass.h>
12#include <reset.h>
13
14#define RESET 0x000
15
16#define RESET_SEL_PLLRESET BIT(12)
17#define RESET_PLLRESET BIT(8)
18
19#define RESET_SEL_P2RESET BIT(5)
20#define RESET_SEL_P1RESET BIT(4)
21#define RESET_PHYRST_2 BIT(1)
22#define RESET_PHYRST_1 BIT(0)
23
24#define PHY_RESET_MASK (RESET_PHYRST_1 | RESET_PHYRST_2)
25
26#define NUM_PORTS 2
27
28static int rzg2l_usbphy_ctrl_assert(struct reset_ctl *reset_ctl)
29{
30 struct rzg2l_usbphy_ctrl_priv *priv = dev_get_priv(reset_ctl->dev);
31 u32 val;
32
33 val = readl(priv->regs + RESET);
34 val |= reset_ctl->id ? RESET_PHYRST_2 : RESET_PHYRST_1;
35
36 /* If both ports are in reset, we can also place the PLL into reset. */
37 if ((val & PHY_RESET_MASK) == PHY_RESET_MASK)
38 val |= RESET_PLLRESET;
39
40 writel(val, priv->regs + RESET);
41 return 0;
42}
43
44static int rzg2l_usbphy_ctrl_deassert(struct reset_ctl *reset_ctl)
45{
46 struct rzg2l_usbphy_ctrl_priv *priv = dev_get_priv(reset_ctl->dev);
47 u32 val = reset_ctl->id ? RESET_PHYRST_2 : RESET_PHYRST_1;
48
49 /* If either port is out of reset, the PLL must also be out of reset. */
50 val |= RESET_PLLRESET;
51
52 clrbits_le32(priv->regs + RESET, val);
53 return 0;
54}
55
56static int rzg2l_usbphy_ctrl_of_xlate(struct reset_ctl *reset_ctl,
57 struct ofnode_phandle_args *args)
58{
59 if (args->args[0] >= NUM_PORTS)
60 return -EINVAL;
61
62 reset_ctl->id = args->args[0];
63 return 0;
64}
65
66struct reset_ops rzg2l_usbphy_ctrl_ops = {
67 .rst_assert = rzg2l_usbphy_ctrl_assert,
68 .rst_deassert = rzg2l_usbphy_ctrl_deassert,
69 .of_xlate = rzg2l_usbphy_ctrl_of_xlate,
70};
71
72static int rzg2l_usbphy_ctrl_probe(struct udevice *dev)
73{
74 struct rzg2l_usbphy_ctrl_priv *priv = dev_get_priv(dev);
75 struct reset_ctl rst;
76 int ret;
77
78 priv->regs = dev_read_addr(dev);
79
80 ret = reset_get_by_index(dev, 0, &rst);
81 if (ret < 0) {
82 dev_err(dev, "failed to get reset line: %d\n", ret);
83 return ret;
84 }
85
86 ret = reset_deassert(&rst);
87 if (ret < 0) {
88 dev_err(dev, "failed to de-assert reset line: %d\n", ret);
89 return ret;
90 }
91
92 /* put pll and phy into reset state */
93 setbits_le32(priv->regs + RESET,
94 RESET_SEL_PLLRESET | RESET_PLLRESET |
95 RESET_SEL_P1RESET | RESET_PHYRST_1 |
96 RESET_SEL_P2RESET | RESET_PHYRST_2);
97
98 return 0;
99}
100
101static const struct udevice_id rzg2l_usbphy_ctrl_ids[] = {
102 { .compatible = "renesas,rzg2l-usbphy-ctrl", },
103 { /* sentinel */ }
104};
105
106U_BOOT_DRIVER(rzg2l_usbphy_ctrl) = {
107 .name = "rzg2l_usbphy_ctrl",
108 .id = UCLASS_RESET,
109 .of_match = rzg2l_usbphy_ctrl_ids,
110 .probe = rzg2l_usbphy_ctrl_probe,
111 .ops = &rzg2l_usbphy_ctrl_ops,
112 .priv_auto = sizeof(struct rzg2l_usbphy_ctrl_priv),
113};