ath79: do not build TP-Link tiny images by default
[oweals/openwrt.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);