blob: 569fbfd35c81def0560deef85b2e689585aa305b [file] [log] [blame]
Mason Huo08059f02023-07-25 17:46:48 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * StarFive PLDA PCIe host controller driver
4 *
5 * Copyright (C) 2023 StarFive Technology Co., Ltd.
6 * Author: Mason Huo <mason.huo@starfivetech.com>
7 *
8 */
9
Mason Huo08059f02023-07-25 17:46:48 +080010#include <clk.h>
11#include <dm.h>
12#include <pci.h>
13#include <pci_ids.h>
14#include <power-domain.h>
15#include <regmap.h>
16#include <reset.h>
17#include <syscon.h>
18#include <asm/global_data.h>
19#include <asm/io.h>
20#include <asm-generic/gpio.h>
21#include <dm/device_compat.h>
22#include <dm/pinctrl.h>
23#include <linux/delay.h>
24#include <linux/iopoll.h>
25#include "pcie_plda_common.h"
26
27/* system control */
28#define STG_SYSCON_K_RP_NEP_MASK BIT(8)
29#define STG_SYSCON_AXI4_SLVL_ARFUNC_MASK GENMASK(22, 8)
30#define STG_SYSCON_AXI4_SLVL_ARFUNC_SHIFT 8
31#define STG_SYSCON_AXI4_SLVL_AWFUNC_MASK GENMASK(14, 0)
32#define STG_SYSCON_CLKREQ_MASK BIT(22)
33#define STG_SYSCON_CKREF_SRC_SHIFT 18
34#define STG_SYSCON_CKREF_SRC_MASK GENMASK(19, 18)
35
36DECLARE_GLOBAL_DATA_PTR;
37
38struct starfive_pcie {
39 struct pcie_plda plda;
40 struct clk_bulk clks;
41 struct reset_ctl_bulk rsts;
42 struct gpio_desc reset_gpio;
43 struct regmap *regmap;
44 u32 stg_arfun;
45 u32 stg_awfun;
46 u32 stg_rp_nep;
47};
48
49static int starfive_pcie_atr_init(struct starfive_pcie *priv)
50{
51 struct udevice *ctlr = pci_get_controller(priv->plda.dev);
52 struct pci_controller *hose = dev_get_uclass_priv(ctlr);
53 int i, ret;
54
55 /*
56 * As the two host bridges in JH7110 soc have the same default
57 * address translation table, this cause the second root port can't
58 * access it's host bridge config space correctly.
59 * To workaround, config the ATR of host bridge config space by SW.
60 */
61
62 ret = plda_pcie_set_atr_entry(&priv->plda,
63 (phys_addr_t)priv->plda.cfg_base, 0,
64 priv->plda.cfg_size,
65 XR3PCI_ATR_TRSLID_PCIE_CONFIG);
66 if (ret)
67 return ret;
68
69 for (i = 0; i < hose->region_count; i++) {
70 if (hose->regions[i].flags == PCI_REGION_SYS_MEMORY)
71 continue;
72
73 /* Only support identity mappings. */
74 if (hose->regions[i].bus_start !=
75 hose->regions[i].phys_start)
76 return -EINVAL;
77
78 ret = plda_pcie_set_atr_entry(&priv->plda,
79 hose->regions[i].phys_start,
80 hose->regions[i].bus_start,
81 hose->regions[i].size,
82 XR3PCI_ATR_TRSLID_PCIE_MEMORY);
83 if (ret)
84 return ret;
85 }
86
87 return 0;
88}
89
90static int starfive_pcie_get_syscon(struct udevice *dev)
91{
92 struct starfive_pcie *priv = dev_get_priv(dev);
93 struct udevice *syscon;
94 struct ofnode_phandle_args syscfg_phandle;
95 u32 cells[4];
96 int ret;
97
98 /* get corresponding syscon phandle */
99 ret = dev_read_phandle_with_args(dev, "starfive,stg-syscon", NULL, 0, 0,
100 &syscfg_phandle);
101
102 if (ret < 0) {
103 dev_err(dev, "Can't get syscfg phandle: %d\n", ret);
104 return ret;
105 }
106
107 ret = uclass_get_device_by_ofnode(UCLASS_SYSCON, syscfg_phandle.node,
108 &syscon);
109 if (ret) {
110 dev_err(dev, "Unable to find syscon device (%d)\n", ret);
111 return ret;
112 }
113
114 priv->regmap = syscon_get_regmap(syscon);
115 if (!priv->regmap) {
116 dev_err(dev, "Unable to find regmap\n");
117 return -ENODEV;
118 }
119
120 /* get syscon register offset */
121 ret = dev_read_u32_array(dev, "starfive,stg-syscon",
122 cells, ARRAY_SIZE(cells));
123 if (ret) {
124 dev_err(dev, "Get syscon register err %d\n", ret);
125 return -EINVAL;
126 }
127
128 dev_dbg(dev, "Get syscon values: %x, %x, %x\n",
129 cells[1], cells[2], cells[3]);
130 priv->stg_arfun = cells[1];
131 priv->stg_awfun = cells[2];
132 priv->stg_rp_nep = cells[3];
133
134 return 0;
135}
136
137static int starfive_pcie_parse_dt(struct udevice *dev)
138{
139 struct starfive_pcie *priv = dev_get_priv(dev);
140 int ret;
141
142 priv->plda.reg_base = (void *)dev_read_addr_name(dev, "reg");
143 if (priv->plda.reg_base == (void __iomem *)FDT_ADDR_T_NONE) {
144 dev_err(dev, "Missing required reg address range\n");
145 return -EINVAL;
146 }
147
148 priv->plda.cfg_base =
149 (void *)dev_read_addr_size_name(dev,
150 "config",
151 &priv->plda.cfg_size);
152 if (priv->plda.cfg_base == (void __iomem *)FDT_ADDR_T_NONE) {
153 dev_err(dev, "Missing required config address range");
154 return -EINVAL;
155 }
156
157 ret = starfive_pcie_get_syscon(dev);
158 if (ret) {
159 dev_err(dev, "Can't get syscon: %d\n", ret);
160 return ret;
161 }
162
163 ret = reset_get_bulk(dev, &priv->rsts);
164 if (ret) {
165 dev_err(dev, "Can't get reset: %d\n", ret);
166 return ret;
167 }
168
169 ret = clk_get_bulk(dev, &priv->clks);
170 if (ret) {
171 dev_err(dev, "Can't get clock: %d\n", ret);
172 return ret;
173 }
174
175 ret = gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset_gpio,
176 GPIOD_IS_OUT);
177 if (ret) {
178 dev_err(dev, "Can't get reset-gpio: %d\n", ret);
179 return ret;
180 }
181
182 if (!dm_gpio_is_valid(&priv->reset_gpio)) {
183 dev_err(dev, "reset-gpio is not valid\n");
184 return -EINVAL;
185 }
186 return 0;
187}
188
189static int starfive_pcie_init_port(struct udevice *dev)
190{
191 int ret, i;
192 struct starfive_pcie *priv = dev_get_priv(dev);
193 struct pcie_plda *plda = &priv->plda;
194
195 ret = clk_enable_bulk(&priv->clks);
196 if (ret) {
197 dev_err(dev, "Failed to enable clks (ret=%d)\n", ret);
198 return ret;
199 }
200
201 ret = reset_deassert_bulk(&priv->rsts);
202 if (ret) {
203 dev_err(dev, "Failed to deassert resets (ret=%d)\n", ret);
204 goto err_deassert_clk;
205 }
206
207 dm_gpio_set_value(&priv->reset_gpio, 1);
208 /* Disable physical functions except #0 */
209 for (i = 1; i < PLDA_FUNC_NUM; i++) {
210 regmap_update_bits(priv->regmap,
211 priv->stg_arfun,
212 STG_SYSCON_AXI4_SLVL_ARFUNC_MASK,
213 (i << PLDA_PHY_FUNC_SHIFT) <<
214 STG_SYSCON_AXI4_SLVL_ARFUNC_SHIFT);
215 regmap_update_bits(priv->regmap,
216 priv->stg_awfun,
217 STG_SYSCON_AXI4_SLVL_AWFUNC_MASK,
218 i << PLDA_PHY_FUNC_SHIFT);
219
220 plda_pcie_disable_func(plda);
221 }
222
223 /* Disable physical functions */
224 regmap_update_bits(priv->regmap,
225 priv->stg_arfun,
226 STG_SYSCON_AXI4_SLVL_ARFUNC_MASK,
227 0);
228 regmap_update_bits(priv->regmap,
229 priv->stg_awfun,
230 STG_SYSCON_AXI4_SLVL_AWFUNC_MASK,
231 0);
232
233 plda_pcie_enable_root_port(plda);
234
235 /* PCIe PCI Standard Configuration Identification Settings. */
236 plda_pcie_set_standard_class(plda);
237
238 /*
239 * The LTR message forwarding of PCIe Message Reception was set by core
240 * as default, but the forward id & addr are also need to be reset.
241 * If we do not disable LTR message forwarding here, or set a legal
242 * forwarding address, the kernel will get stuck after this driver probe.
243 * To workaround, disable the LTR message forwarding support on
244 * PCIe Message Reception.
245 */
246 plda_pcie_disable_ltr(plda);
247
248 /* Prefetchable memory window 64-bit addressing support */
249 plda_pcie_set_pref_win_64bit(plda);
250 starfive_pcie_atr_init(priv);
251
252 dm_gpio_set_value(&priv->reset_gpio, 0);
253 /* Ensure that PERST in default at least 300 ms */
254 mdelay(300);
255
256 return 0;
257
258err_deassert_clk:
259 clk_disable_bulk(&priv->clks);
260 return ret;
261}
262
263static int starfive_pcie_probe(struct udevice *dev)
264{
265 struct starfive_pcie *priv = dev_get_priv(dev);
266 int ret;
267
268 priv->plda.atr_table_num = 0;
269 priv->plda.dev = dev;
270
271 ret = starfive_pcie_parse_dt(dev);
272 if (ret)
273 return ret;
274
275 regmap_update_bits(priv->regmap,
276 priv->stg_rp_nep,
277 STG_SYSCON_K_RP_NEP_MASK,
278 STG_SYSCON_K_RP_NEP_MASK);
279
280 regmap_update_bits(priv->regmap,
281 priv->stg_awfun,
282 STG_SYSCON_CKREF_SRC_MASK,
283 2 << STG_SYSCON_CKREF_SRC_SHIFT);
284
285 regmap_update_bits(priv->regmap,
286 priv->stg_awfun,
287 STG_SYSCON_CLKREQ_MASK,
288 STG_SYSCON_CLKREQ_MASK);
289
290 ret = starfive_pcie_init_port(dev);
291 if (ret)
292 return ret;
293
294 dev_err(dev, "Starfive PCIe bus probed.\n");
295
296 return 0;
297}
298
299static const struct dm_pci_ops starfive_pcie_ops = {
300 .read_config = plda_pcie_config_read,
301 .write_config = plda_pcie_config_write,
302};
303
304static const struct udevice_id starfive_pcie_ids[] = {
305 { .compatible = "starfive,jh7110-pcie" },
306 { }
307};
308
309U_BOOT_DRIVER(starfive_pcie_drv) = {
310 .name = "starfive_7110_pcie",
311 .id = UCLASS_PCI,
312 .of_match = starfive_pcie_ids,
313 .ops = &starfive_pcie_ops,
314 .probe = starfive_pcie_probe,
315 .priv_auto = sizeof(struct starfive_pcie),
316};