1 // 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-internal.h>
9 #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 
rzg2l_usbphy_ctrl_assert(struct reset_ctl * reset_ctl)29 static 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 
rzg2l_usbphy_ctrl_deassert(struct reset_ctl * reset_ctl)45 static 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 
rzg2l_usbphy_ctrl_of_xlate(struct reset_ctl * reset_ctl,struct ofnode_phandle_args * args)57 static 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 
67 struct 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 
rzg2l_usbphy_ctrl_probe(struct udevice * dev)73 static 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 
102 static const struct udevice_id rzg2l_usbphy_ctrl_ids[] = {
103 	{ .compatible = "renesas,rzg2l-usbphy-ctrl", },
104 	{ /* sentinel */ }
105 };
106 
rzg2l_usbphy_ctrl_bind(struct udevice * dev)107 static 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 
134 U_BOOT_DRIVER(rzg2l_usbphy_ctrl) = {
135 	.name           = "rzg2l_usbphy_ctrl",
136 	.id             = UCLASS_RESET,
137 	.of_match       = rzg2l_usbphy_ctrl_ids,
138 	.bind           = rzg2l_usbphy_ctrl_bind,
139 	.probe          = rzg2l_usbphy_ctrl_probe,
140 	.ops            = &rzg2l_usbphy_ctrl_ops,
141 	.priv_auto      = sizeof(struct rzg2l_usbphy_ctrl_priv),
142 };
143