ramips: replace pinctrl property names
[openwrt/staging/wigyori.git] / target / linux / ramips / patches-5.4 / 0110-staging-mt7621-pci-phy-avoid-to-create-to-different-.patch
1 From 91eb47531421f0e8c9bc4594b4a7caa0e59dc83e Mon Sep 17 00:00:00 2001
2 From: Sergio Paracuellos <sergio.paracuellos@gmail.com>
3 Date: Fri, 20 Mar 2020 12:01:19 +0100
4 Subject: [PATCH] staging: mt7621-pci-phy: avoid to create to different phys
5 for a dual port one
6
7 This soc has two phy's for the pcie one of them using just a different
8 register for settig it up but sharing all the rest of the config. Until
9 now we was presenting this schema as three different phy's in the device
10 tree using the 'phy-cells' node property to discriminate an index and
11 setting up a complete phy for the dual port index. This sometimes worked
12 properly but reconfiguring the same registers twice presents sometimes
13 some unstable pcie links and the ports was not properly being detected.
14 The problems only appears on hard resets and soft resets was properly
15 working. Instead of having this schema just set two phy's in the device
16 ree and use the 'phy-cells' property to say if the port has or not a dual
17 port. Doing this configuration and set up becomes easier, LOC is decreased
18 and the behaviour also gets deterministic with properly and stable pcie
19 links in both hard and soft resets.
20
21 Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
22 Link: https://lore.kernel.org/r/20200320110123.9907-2-sergio.paracuellos@gmail.com
23 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
24 ---
25 drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c | 144 ++++++++++--------------
26 1 file changed, 59 insertions(+), 85 deletions(-)
27
28 --- a/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
29 +++ b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
30 @@ -78,31 +78,21 @@
31 #define MAX_PHYS 2
32
33 /**
34 - * struct mt7621_pci_phy_instance - Mt7621 Pcie PHY device
35 - * @phy: pointer to the kernel PHY device
36 - * @port_base: base register
37 - * @index: internal ID to identify the Mt7621 PCIe PHY
38 - */
39 -struct mt7621_pci_phy_instance {
40 - struct phy *phy;
41 - void __iomem *port_base;
42 - u32 index;
43 -};
44 -
45 -/**
46 * struct mt7621_pci_phy - Mt7621 Pcie PHY core
47 * @dev: pointer to device
48 * @regmap: kernel regmap pointer
49 - * @phys: pointer to Mt7621 PHY device
50 - * @nphys: number of PHY devices for this core
51 + * @phy: pointer to the kernel PHY device
52 + * @port_base: base register
53 + * @has_dual_port: if the phy has dual ports.
54 * @bypass_pipe_rst: mark if 'mt7621_bypass_pipe_rst'
55 * needs to be executed. Depends on chip revision.
56 */
57 struct mt7621_pci_phy {
58 struct device *dev;
59 struct regmap *regmap;
60 - struct mt7621_pci_phy_instance **phys;
61 - int nphys;
62 + struct phy *phy;
63 + void __iomem *port_base;
64 + bool has_dual_port;
65 bool bypass_pipe_rst;
66 };
67
68 @@ -130,23 +120,23 @@ static inline void mt7621_phy_rmw(struct
69 phy_write(phy, val, reg);
70 }
71
72 -static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy,
73 - struct mt7621_pci_phy_instance *instance)
74 +static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy)
75 {
76 - u32 offset = (instance->index != 1) ?
77 - RG_PE1_PIPE_REG : RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH;
78 + mt7621_phy_rmw(phy, RG_PE1_PIPE_REG, 0, RG_PE1_PIPE_RST);
79 + mt7621_phy_rmw(phy, RG_PE1_PIPE_REG, 0, RG_PE1_PIPE_CMD_FRC);
80
81 - mt7621_phy_rmw(phy, offset,
82 - RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC,
83 - RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC);
84 + if (phy->has_dual_port) {
85 + mt7621_phy_rmw(phy, RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH,
86 + 0, RG_PE1_PIPE_RST);
87 + mt7621_phy_rmw(phy, RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH,
88 + 0, RG_PE1_PIPE_CMD_FRC);
89 + }
90 }
91
92 -static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy,
93 - struct mt7621_pci_phy_instance *instance)
94 +static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy)
95 {
96 struct device *dev = phy->dev;
97 u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0);
98 - u32 offset;
99
100 reg = (reg >> 6) & 0x7;
101 /* Set PCIe Port PHY to disable SSC */
102 @@ -156,10 +146,13 @@ static void mt7621_set_phy_for_ssc(struc
103 RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE_VAL(0x00));
104
105 /* disable port */
106 - offset = (instance->index != 1) ?
107 - RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
108 - mt7621_phy_rmw(phy, offset,
109 - RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
110 + mt7621_phy_rmw(phy, RG_PE1_FRC_PHY_REG,
111 + RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
112 +
113 + if (phy->has_dual_port) {
114 + mt7621_phy_rmw(phy, RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH,
115 + RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
116 + }
117
118 if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */
119 /* Set Pre-divider ratio (for host mode) */
120 @@ -223,43 +216,44 @@ static void mt7621_set_phy_for_ssc(struc
121
122 static int mt7621_pci_phy_init(struct phy *phy)
123 {
124 - struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
125 - struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent);
126 + struct mt7621_pci_phy *mphy = phy_get_drvdata(phy);
127
128 if (mphy->bypass_pipe_rst)
129 - mt7621_bypass_pipe_rst(mphy, instance);
130 + mt7621_bypass_pipe_rst(mphy);
131
132 - mt7621_set_phy_for_ssc(mphy, instance);
133 + mt7621_set_phy_for_ssc(mphy);
134
135 return 0;
136 }
137
138 static int mt7621_pci_phy_power_on(struct phy *phy)
139 {
140 - struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
141 - struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent);
142 - u32 offset = (instance->index != 1) ?
143 - RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
144 + struct mt7621_pci_phy *mphy = phy_get_drvdata(phy);
145
146 /* Enable PHY and disable force mode */
147 - mt7621_phy_rmw(mphy, offset,
148 - RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN,
149 - RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN);
150 + mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG,
151 + RG_PE1_FRC_PHY_EN, RG_PE1_PHY_EN);
152 +
153 + if (mphy->has_dual_port) {
154 + mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH,
155 + RG_PE1_FRC_PHY_EN, RG_PE1_PHY_EN);
156 + }
157
158 return 0;
159 }
160
161 static int mt7621_pci_phy_power_off(struct phy *phy)
162 {
163 - struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy);
164 - struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent);
165 - u32 offset = (instance->index != 1) ?
166 - RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH;
167 + struct mt7621_pci_phy *mphy = phy_get_drvdata(phy);
168
169 /* Disable PHY */
170 - mt7621_phy_rmw(mphy, offset,
171 - RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN,
172 - RG_PE1_FRC_PHY_EN);
173 + mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG,
174 + RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
175 +
176 + if (mphy->has_dual_port) {
177 + mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH,
178 + RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
179 + }
180
181 return 0;
182 }
183 @@ -282,13 +276,15 @@ static struct phy *mt7621_pcie_phy_of_xl
184 {
185 struct mt7621_pci_phy *mt7621_phy = dev_get_drvdata(dev);
186
187 - if (args->args_count == 0)
188 - return mt7621_phy->phys[0]->phy;
189 -
190 if (WARN_ON(args->args[0] >= MAX_PHYS))
191 return ERR_PTR(-ENODEV);
192
193 - return mt7621_phy->phys[args->args[0]]->phy;
194 + mt7621_phy->has_dual_port = args->args[0];
195 +
196 + dev_info(dev, "PHY for 0x%08x (dual port = %d)\n",
197 + (unsigned int)mt7621_phy->port_base, mt7621_phy->has_dual_port);
198 +
199 + return mt7621_phy->phy;
200 }
201
202 static const struct soc_device_attribute mt7621_pci_quirks_match[] = {
203 @@ -309,19 +305,11 @@ static int mt7621_pci_phy_probe(struct p
204 struct phy_provider *provider;
205 struct mt7621_pci_phy *phy;
206 struct resource *res;
207 - int port;
208 - void __iomem *port_base;
209
210 phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
211 if (!phy)
212 return -ENOMEM;
213
214 - phy->nphys = MAX_PHYS;
215 - phy->phys = devm_kcalloc(dev, phy->nphys,
216 - sizeof(*phy->phys), GFP_KERNEL);
217 - if (!phy->phys)
218 - return -ENOMEM;
219 -
220 attr = soc_device_match(mt7621_pci_quirks_match);
221 if (attr)
222 phy->bypass_pipe_rst = true;
223 @@ -335,39 +323,25 @@ static int mt7621_pci_phy_probe(struct p
224 return -ENXIO;
225 }
226
227 - port_base = devm_ioremap_resource(dev, res);
228 - if (IS_ERR(port_base)) {
229 + phy->port_base = devm_ioremap_resource(dev, res);
230 + if (IS_ERR(phy->port_base)) {
231 dev_err(dev, "failed to remap phy regs\n");
232 - return PTR_ERR(port_base);
233 + return PTR_ERR(phy->port_base);
234 }
235
236 - phy->regmap = devm_regmap_init_mmio(phy->dev, port_base,
237 + phy->regmap = devm_regmap_init_mmio(phy->dev, phy->port_base,
238 &mt7621_pci_phy_regmap_config);
239 if (IS_ERR(phy->regmap))
240 return PTR_ERR(phy->regmap);
241
242 - for (port = 0; port < MAX_PHYS; port++) {
243 - struct mt7621_pci_phy_instance *instance;
244 - struct phy *pphy;
245 -
246 - instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
247 - if (!instance)
248 - return -ENOMEM;
249 -
250 - phy->phys[port] = instance;
251 -
252 - pphy = devm_phy_create(dev, dev->of_node, &mt7621_pci_phy_ops);
253 - if (IS_ERR(phy)) {
254 - dev_err(dev, "failed to create phy\n");
255 - return PTR_ERR(phy);
256 - }
257 -
258 - instance->port_base = port_base;
259 - instance->phy = pphy;
260 - instance->index = port;
261 - phy_set_drvdata(pphy, instance);
262 + phy->phy = devm_phy_create(dev, dev->of_node, &mt7621_pci_phy_ops);
263 + if (IS_ERR(phy)) {
264 + dev_err(dev, "failed to create phy\n");
265 + return PTR_ERR(phy);
266 }
267
268 + phy_set_drvdata(phy->phy, phy);
269 +
270 provider = devm_of_phy_provider_register(dev, mt7621_pcie_phy_of_xlate);
271
272 return PTR_ERR_OR_ZERO(provider);