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
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.
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>
25 drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c | 144 ++++++++++--------------
26 1 file changed, 59 insertions(+), 85 deletions(-)
28 --- a/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
29 +++ b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c
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
39 -struct mt7621_pci_phy_instance {
41 - void __iomem *port_base;
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.
57 struct mt7621_pci_phy {
59 struct regmap *regmap;
60 - struct mt7621_pci_phy_instance **phys;
63 + void __iomem *port_base;
68 @@ -130,23 +120,23 @@ static inline void mt7621_phy_rmw(struct
69 phy_write(phy, val, reg);
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)
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);
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);
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)
96 struct device *dev = phy->dev;
97 u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0);
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));
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);
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);
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
122 static int mt7621_pci_phy_init(struct phy *phy)
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);
128 if (mphy->bypass_pipe_rst)
129 - mt7621_bypass_pipe_rst(mphy, instance);
130 + mt7621_bypass_pipe_rst(mphy);
132 - mt7621_set_phy_for_ssc(mphy, instance);
133 + mt7621_set_phy_for_ssc(mphy);
138 static int mt7621_pci_phy_power_on(struct phy *phy)
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);
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);
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);
161 static int mt7621_pci_phy_power_off(struct phy *phy)
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);
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);
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);
183 @@ -282,13 +276,15 @@ static struct phy *mt7621_pcie_phy_of_xl
185 struct mt7621_pci_phy *mt7621_phy = dev_get_drvdata(dev);
187 - if (args->args_count == 0)
188 - return mt7621_phy->phys[0]->phy;
190 if (WARN_ON(args->args[0] >= MAX_PHYS))
191 return ERR_PTR(-ENODEV);
193 - return mt7621_phy->phys[args->args[0]]->phy;
194 + mt7621_phy->has_dual_port = args->args[0];
196 + dev_info(dev, "PHY for 0x%08x (dual port = %d)\n",
197 + (unsigned int)mt7621_phy->port_base, mt7621_phy->has_dual_port);
199 + return mt7621_phy->phy;
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;
208 - void __iomem *port_base;
210 phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
214 - phy->nphys = MAX_PHYS;
215 - phy->phys = devm_kcalloc(dev, phy->nphys,
216 - sizeof(*phy->phys), GFP_KERNEL);
220 attr = soc_device_match(mt7621_pci_quirks_match);
222 phy->bypass_pipe_rst = true;
223 @@ -335,39 +323,25 @@ static int mt7621_pci_phy_probe(struct p
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);
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);
242 - for (port = 0; port < MAX_PHYS; port++) {
243 - struct mt7621_pci_phy_instance *instance;
246 - instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
250 - phy->phys[port] = instance;
252 - pphy = devm_phy_create(dev, dev->of_node, &mt7621_pci_phy_ops);
254 - dev_err(dev, "failed to create phy\n");
255 - return PTR_ERR(phy);
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);
264 + dev_err(dev, "failed to create phy\n");
265 + return PTR_ERR(phy);
268 + phy_set_drvdata(phy->phy, phy);
270 provider = devm_of_phy_provider_register(dev, mt7621_pcie_phy_of_xlate);
272 return PTR_ERR_OR_ZERO(provider);