1 | // SPDX-License-Identifier: GPL-2.0 |
---|---|
2 | /* |
3 | * PCIe host controller driver for Kirin Phone SoCs |
4 | * |
5 | * Copyright (C) 2017 HiSilicon Electronics Co., Ltd. |
6 | * https://www.huawei.com |
7 | * |
8 | * Author: Xiaowei Song <songxiaowei@huawei.com> |
9 | */ |
10 | |
11 | #include <linux/clk.h> |
12 | #include <linux/compiler.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/err.h> |
15 | #include <linux/gpio.h> |
16 | #include <linux/gpio/consumer.h> |
17 | #include <linux/interrupt.h> |
18 | #include <linux/mfd/syscon.h> |
19 | #include <linux/of.h> |
20 | #include <linux/of_gpio.h> |
21 | #include <linux/of_pci.h> |
22 | #include <linux/phy/phy.h> |
23 | #include <linux/pci.h> |
24 | #include <linux/pci_regs.h> |
25 | #include <linux/platform_device.h> |
26 | #include <linux/regmap.h> |
27 | #include <linux/resource.h> |
28 | #include <linux/types.h> |
29 | #include "pcie-designware.h" |
30 | |
31 | #define to_kirin_pcie(x) dev_get_drvdata((x)->dev) |
32 | |
33 | /* PCIe ELBI registers */ |
34 | #define SOC_PCIECTRL_CTRL0_ADDR 0x000 |
35 | #define SOC_PCIECTRL_CTRL1_ADDR 0x004 |
36 | #define PCIE_ELBI_SLV_DBI_ENABLE (0x1 << 21) |
37 | |
38 | /* info located in APB */ |
39 | #define PCIE_APP_LTSSM_ENABLE 0x01c |
40 | #define PCIE_APB_PHY_STATUS0 0x400 |
41 | #define PCIE_LINKUP_ENABLE (0x8020) |
42 | #define PCIE_LTSSM_ENABLE_BIT (0x1 << 11) |
43 | |
44 | /* info located in sysctrl */ |
45 | #define SCTRL_PCIE_CMOS_OFFSET 0x60 |
46 | #define SCTRL_PCIE_CMOS_BIT 0x10 |
47 | #define SCTRL_PCIE_ISO_OFFSET 0x44 |
48 | #define SCTRL_PCIE_ISO_BIT 0x30 |
49 | #define SCTRL_PCIE_HPCLK_OFFSET 0x190 |
50 | #define SCTRL_PCIE_HPCLK_BIT 0x184000 |
51 | #define SCTRL_PCIE_OE_OFFSET 0x14a |
52 | #define PCIE_DEBOUNCE_PARAM 0xF0F400 |
53 | #define PCIE_OE_BYPASS (0x3 << 28) |
54 | |
55 | /* |
56 | * Max number of connected PCI slots at an external PCI bridge |
57 | * |
58 | * This is used on HiKey 970, which has a PEX 8606 bridge with 4 connected |
59 | * lanes (lane 0 upstream, and the other three lanes, one connected to an |
60 | * in-board Ethernet adapter and the other two connected to M.2 and mini |
61 | * PCI slots. |
62 | * |
63 | * Each slot has a different clock source and uses a separate PERST# pin. |
64 | */ |
65 | #define MAX_PCI_SLOTS 3 |
66 | |
67 | enum pcie_kirin_phy_type { |
68 | PCIE_KIRIN_INTERNAL_PHY, |
69 | PCIE_KIRIN_EXTERNAL_PHY |
70 | }; |
71 | |
72 | struct kirin_pcie { |
73 | enum pcie_kirin_phy_type type; |
74 | |
75 | struct dw_pcie *pci; |
76 | struct regmap *apb; |
77 | struct phy *phy; |
78 | void *phy_priv; /* only for PCIE_KIRIN_INTERNAL_PHY */ |
79 | |
80 | /* DWC PERST# */ |
81 | int gpio_id_dwc_perst; |
82 | |
83 | /* Per-slot PERST# */ |
84 | int num_slots; |
85 | int gpio_id_reset[MAX_PCI_SLOTS]; |
86 | const char *reset_names[MAX_PCI_SLOTS]; |
87 | |
88 | /* Per-slot clkreq */ |
89 | int n_gpio_clkreq; |
90 | int gpio_id_clkreq[MAX_PCI_SLOTS]; |
91 | const char *clkreq_names[MAX_PCI_SLOTS]; |
92 | }; |
93 | |
94 | /* |
95 | * Kirin 960 PHY. Can't be split into a PHY driver without changing the |
96 | * DT schema. |
97 | */ |
98 | |
99 | #define REF_CLK_FREQ 100000000 |
100 | |
101 | /* PHY info located in APB */ |
102 | #define PCIE_APB_PHY_CTRL0 0x0 |
103 | #define PCIE_APB_PHY_CTRL1 0x4 |
104 | #define PCIE_APB_PHY_STATUS0 0x400 |
105 | #define PIPE_CLK_STABLE BIT(19) |
106 | #define PHY_REF_PAD_BIT BIT(8) |
107 | #define PHY_PWR_DOWN_BIT BIT(22) |
108 | #define PHY_RST_ACK_BIT BIT(16) |
109 | |
110 | /* peri_crg ctrl */ |
111 | #define CRGCTRL_PCIE_ASSERT_OFFSET 0x88 |
112 | #define CRGCTRL_PCIE_ASSERT_BIT 0x8c000000 |
113 | |
114 | /* Time for delay */ |
115 | #define REF_2_PERST_MIN 21000 |
116 | #define REF_2_PERST_MAX 25000 |
117 | #define PERST_2_ACCESS_MIN 10000 |
118 | #define PERST_2_ACCESS_MAX 12000 |
119 | #define PIPE_CLK_WAIT_MIN 550 |
120 | #define PIPE_CLK_WAIT_MAX 600 |
121 | #define TIME_CMOS_MIN 100 |
122 | #define TIME_CMOS_MAX 105 |
123 | #define TIME_PHY_PD_MIN 10 |
124 | #define TIME_PHY_PD_MAX 11 |
125 | |
126 | struct hi3660_pcie_phy { |
127 | struct device *dev; |
128 | void __iomem *base; |
129 | struct regmap *crgctrl; |
130 | struct regmap *sysctrl; |
131 | struct clk *apb_sys_clk; |
132 | struct clk *apb_phy_clk; |
133 | struct clk *phy_ref_clk; |
134 | struct clk *aclk; |
135 | struct clk *aux_clk; |
136 | }; |
137 | |
138 | /* Registers in PCIePHY */ |
139 | static inline void kirin_apb_phy_writel(struct hi3660_pcie_phy *hi3660_pcie_phy, |
140 | u32 val, u32 reg) |
141 | { |
142 | writel(val, addr: hi3660_pcie_phy->base + reg); |
143 | } |
144 | |
145 | static inline u32 kirin_apb_phy_readl(struct hi3660_pcie_phy *hi3660_pcie_phy, |
146 | u32 reg) |
147 | { |
148 | return readl(addr: hi3660_pcie_phy->base + reg); |
149 | } |
150 | |
151 | static int hi3660_pcie_phy_get_clk(struct hi3660_pcie_phy *phy) |
152 | { |
153 | struct device *dev = phy->dev; |
154 | |
155 | phy->phy_ref_clk = devm_clk_get(dev, id: "pcie_phy_ref"); |
156 | if (IS_ERR(ptr: phy->phy_ref_clk)) |
157 | return PTR_ERR(ptr: phy->phy_ref_clk); |
158 | |
159 | phy->aux_clk = devm_clk_get(dev, id: "pcie_aux"); |
160 | if (IS_ERR(ptr: phy->aux_clk)) |
161 | return PTR_ERR(ptr: phy->aux_clk); |
162 | |
163 | phy->apb_phy_clk = devm_clk_get(dev, id: "pcie_apb_phy"); |
164 | if (IS_ERR(ptr: phy->apb_phy_clk)) |
165 | return PTR_ERR(ptr: phy->apb_phy_clk); |
166 | |
167 | phy->apb_sys_clk = devm_clk_get(dev, id: "pcie_apb_sys"); |
168 | if (IS_ERR(ptr: phy->apb_sys_clk)) |
169 | return PTR_ERR(ptr: phy->apb_sys_clk); |
170 | |
171 | phy->aclk = devm_clk_get(dev, id: "pcie_aclk"); |
172 | if (IS_ERR(ptr: phy->aclk)) |
173 | return PTR_ERR(ptr: phy->aclk); |
174 | |
175 | return 0; |
176 | } |
177 | |
178 | static int hi3660_pcie_phy_get_resource(struct hi3660_pcie_phy *phy) |
179 | { |
180 | struct device *dev = phy->dev; |
181 | struct platform_device *pdev; |
182 | |
183 | /* registers */ |
184 | pdev = container_of(dev, struct platform_device, dev); |
185 | |
186 | phy->base = devm_platform_ioremap_resource_byname(pdev, name: "phy"); |
187 | if (IS_ERR(ptr: phy->base)) |
188 | return PTR_ERR(ptr: phy->base); |
189 | |
190 | phy->crgctrl = syscon_regmap_lookup_by_compatible(s: "hisilicon,hi3660-crgctrl"); |
191 | if (IS_ERR(ptr: phy->crgctrl)) |
192 | return PTR_ERR(ptr: phy->crgctrl); |
193 | |
194 | phy->sysctrl = syscon_regmap_lookup_by_compatible(s: "hisilicon,hi3660-sctrl"); |
195 | if (IS_ERR(ptr: phy->sysctrl)) |
196 | return PTR_ERR(ptr: phy->sysctrl); |
197 | |
198 | return 0; |
199 | } |
200 | |
201 | static int hi3660_pcie_phy_start(struct hi3660_pcie_phy *phy) |
202 | { |
203 | struct device *dev = phy->dev; |
204 | u32 reg_val; |
205 | |
206 | reg_val = kirin_apb_phy_readl(hi3660_pcie_phy: phy, PCIE_APB_PHY_CTRL1); |
207 | reg_val &= ~PHY_REF_PAD_BIT; |
208 | kirin_apb_phy_writel(hi3660_pcie_phy: phy, val: reg_val, PCIE_APB_PHY_CTRL1); |
209 | |
210 | reg_val = kirin_apb_phy_readl(hi3660_pcie_phy: phy, PCIE_APB_PHY_CTRL0); |
211 | reg_val &= ~PHY_PWR_DOWN_BIT; |
212 | kirin_apb_phy_writel(hi3660_pcie_phy: phy, val: reg_val, PCIE_APB_PHY_CTRL0); |
213 | usleep_range(TIME_PHY_PD_MIN, TIME_PHY_PD_MAX); |
214 | |
215 | reg_val = kirin_apb_phy_readl(hi3660_pcie_phy: phy, PCIE_APB_PHY_CTRL1); |
216 | reg_val &= ~PHY_RST_ACK_BIT; |
217 | kirin_apb_phy_writel(hi3660_pcie_phy: phy, val: reg_val, PCIE_APB_PHY_CTRL1); |
218 | |
219 | usleep_range(PIPE_CLK_WAIT_MIN, PIPE_CLK_WAIT_MAX); |
220 | reg_val = kirin_apb_phy_readl(hi3660_pcie_phy: phy, PCIE_APB_PHY_STATUS0); |
221 | if (reg_val & PIPE_CLK_STABLE) { |
222 | dev_err(dev, "PIPE clk is not stable\n"); |
223 | return -EINVAL; |
224 | } |
225 | |
226 | return 0; |
227 | } |
228 | |
229 | static void hi3660_pcie_phy_oe_enable(struct hi3660_pcie_phy *phy) |
230 | { |
231 | u32 val; |
232 | |
233 | regmap_read(map: phy->sysctrl, SCTRL_PCIE_OE_OFFSET, val: &val); |
234 | val |= PCIE_DEBOUNCE_PARAM; |
235 | val &= ~PCIE_OE_BYPASS; |
236 | regmap_write(map: phy->sysctrl, SCTRL_PCIE_OE_OFFSET, val); |
237 | } |
238 | |
239 | static int hi3660_pcie_phy_clk_ctrl(struct hi3660_pcie_phy *phy, bool enable) |
240 | { |
241 | int ret = 0; |
242 | |
243 | if (!enable) |
244 | goto close_clk; |
245 | |
246 | ret = clk_set_rate(clk: phy->phy_ref_clk, REF_CLK_FREQ); |
247 | if (ret) |
248 | return ret; |
249 | |
250 | ret = clk_prepare_enable(clk: phy->phy_ref_clk); |
251 | if (ret) |
252 | return ret; |
253 | |
254 | ret = clk_prepare_enable(clk: phy->apb_sys_clk); |
255 | if (ret) |
256 | goto apb_sys_fail; |
257 | |
258 | ret = clk_prepare_enable(clk: phy->apb_phy_clk); |
259 | if (ret) |
260 | goto apb_phy_fail; |
261 | |
262 | ret = clk_prepare_enable(clk: phy->aclk); |
263 | if (ret) |
264 | goto aclk_fail; |
265 | |
266 | ret = clk_prepare_enable(clk: phy->aux_clk); |
267 | if (ret) |
268 | goto aux_clk_fail; |
269 | |
270 | return 0; |
271 | |
272 | close_clk: |
273 | clk_disable_unprepare(clk: phy->aux_clk); |
274 | aux_clk_fail: |
275 | clk_disable_unprepare(clk: phy->aclk); |
276 | aclk_fail: |
277 | clk_disable_unprepare(clk: phy->apb_phy_clk); |
278 | apb_phy_fail: |
279 | clk_disable_unprepare(clk: phy->apb_sys_clk); |
280 | apb_sys_fail: |
281 | clk_disable_unprepare(clk: phy->phy_ref_clk); |
282 | |
283 | return ret; |
284 | } |
285 | |
286 | static int hi3660_pcie_phy_power_on(struct kirin_pcie *pcie) |
287 | { |
288 | struct hi3660_pcie_phy *phy = pcie->phy_priv; |
289 | int ret; |
290 | |
291 | /* Power supply for Host */ |
292 | regmap_write(map: phy->sysctrl, |
293 | SCTRL_PCIE_CMOS_OFFSET, SCTRL_PCIE_CMOS_BIT); |
294 | usleep_range(TIME_CMOS_MIN, TIME_CMOS_MAX); |
295 | |
296 | hi3660_pcie_phy_oe_enable(phy); |
297 | |
298 | ret = hi3660_pcie_phy_clk_ctrl(phy, enable: true); |
299 | if (ret) |
300 | return ret; |
301 | |
302 | /* ISO disable, PCIeCtrl, PHY assert and clk gate clear */ |
303 | regmap_write(map: phy->sysctrl, |
304 | SCTRL_PCIE_ISO_OFFSET, SCTRL_PCIE_ISO_BIT); |
305 | regmap_write(map: phy->crgctrl, |
306 | CRGCTRL_PCIE_ASSERT_OFFSET, CRGCTRL_PCIE_ASSERT_BIT); |
307 | regmap_write(map: phy->sysctrl, |
308 | SCTRL_PCIE_HPCLK_OFFSET, SCTRL_PCIE_HPCLK_BIT); |
309 | |
310 | ret = hi3660_pcie_phy_start(phy); |
311 | if (ret) |
312 | goto disable_clks; |
313 | |
314 | return 0; |
315 | |
316 | disable_clks: |
317 | hi3660_pcie_phy_clk_ctrl(phy, enable: false); |
318 | return ret; |
319 | } |
320 | |
321 | static int hi3660_pcie_phy_init(struct platform_device *pdev, |
322 | struct kirin_pcie *pcie) |
323 | { |
324 | struct device *dev = &pdev->dev; |
325 | struct hi3660_pcie_phy *phy; |
326 | int ret; |
327 | |
328 | phy = devm_kzalloc(dev, size: sizeof(*phy), GFP_KERNEL); |
329 | if (!phy) |
330 | return -ENOMEM; |
331 | |
332 | pcie->phy_priv = phy; |
333 | phy->dev = dev; |
334 | |
335 | ret = hi3660_pcie_phy_get_clk(phy); |
336 | if (ret) |
337 | return ret; |
338 | |
339 | return hi3660_pcie_phy_get_resource(phy); |
340 | } |
341 | |
342 | static int hi3660_pcie_phy_power_off(struct kirin_pcie *pcie) |
343 | { |
344 | struct hi3660_pcie_phy *phy = pcie->phy_priv; |
345 | |
346 | /* Drop power supply for Host */ |
347 | regmap_write(map: phy->sysctrl, SCTRL_PCIE_CMOS_OFFSET, val: 0x00); |
348 | |
349 | hi3660_pcie_phy_clk_ctrl(phy, enable: false); |
350 | |
351 | return 0; |
352 | } |
353 | |
354 | /* |
355 | * The non-PHY part starts here |
356 | */ |
357 | |
358 | static const struct regmap_config pcie_kirin_regmap_conf = { |
359 | .name = "kirin_pcie_apb", |
360 | .reg_bits = 32, |
361 | .val_bits = 32, |
362 | .reg_stride = 4, |
363 | }; |
364 | |
365 | static int kirin_pcie_get_gpio_enable(struct kirin_pcie *pcie, |
366 | struct platform_device *pdev) |
367 | { |
368 | struct device *dev = &pdev->dev; |
369 | int ret, i; |
370 | |
371 | /* This is an optional property */ |
372 | ret = gpiod_count(dev, con_id: "hisilicon,clken"); |
373 | if (ret < 0) |
374 | return 0; |
375 | |
376 | if (ret > MAX_PCI_SLOTS) { |
377 | dev_err(dev, "Too many GPIO clock requests!\n"); |
378 | return -EINVAL; |
379 | } |
380 | |
381 | pcie->n_gpio_clkreq = ret; |
382 | |
383 | for (i = 0; i < pcie->n_gpio_clkreq; i++) { |
384 | pcie->gpio_id_clkreq[i] = of_get_named_gpio(np: dev->of_node, |
385 | list_name: "hisilicon,clken-gpios", index: i); |
386 | if (pcie->gpio_id_clkreq[i] < 0) |
387 | return pcie->gpio_id_clkreq[i]; |
388 | |
389 | pcie->clkreq_names[i] = devm_kasprintf(dev, GFP_KERNEL, |
390 | fmt: "pcie_clkreq_%d", i); |
391 | if (!pcie->clkreq_names[i]) |
392 | return -ENOMEM; |
393 | } |
394 | |
395 | return 0; |
396 | } |
397 | |
398 | static int kirin_pcie_parse_port(struct kirin_pcie *pcie, |
399 | struct platform_device *pdev, |
400 | struct device_node *node) |
401 | { |
402 | struct device *dev = &pdev->dev; |
403 | struct device_node *parent, *child; |
404 | int ret, slot, i; |
405 | |
406 | for_each_available_child_of_node(node, parent) { |
407 | for_each_available_child_of_node(parent, child) { |
408 | i = pcie->num_slots; |
409 | |
410 | pcie->gpio_id_reset[i] = of_get_named_gpio(np: child, |
411 | list_name: "reset-gpios", index: 0); |
412 | if (pcie->gpio_id_reset[i] < 0) |
413 | continue; |
414 | |
415 | pcie->num_slots++; |
416 | if (pcie->num_slots > MAX_PCI_SLOTS) { |
417 | dev_err(dev, "Too many PCI slots!\n"); |
418 | ret = -EINVAL; |
419 | goto put_node; |
420 | } |
421 | |
422 | ret = of_pci_get_devfn(np: child); |
423 | if (ret < 0) { |
424 | dev_err(dev, "failed to parse devfn: %d\n", ret); |
425 | goto put_node; |
426 | } |
427 | |
428 | slot = PCI_SLOT(ret); |
429 | |
430 | pcie->reset_names[i] = devm_kasprintf(dev, GFP_KERNEL, |
431 | fmt: "pcie_perst_%d", |
432 | slot); |
433 | if (!pcie->reset_names[i]) { |
434 | ret = -ENOMEM; |
435 | goto put_node; |
436 | } |
437 | } |
438 | } |
439 | |
440 | return 0; |
441 | |
442 | put_node: |
443 | of_node_put(node: child); |
444 | of_node_put(node: parent); |
445 | return ret; |
446 | } |
447 | |
448 | static long kirin_pcie_get_resource(struct kirin_pcie *kirin_pcie, |
449 | struct platform_device *pdev) |
450 | { |
451 | struct device *dev = &pdev->dev; |
452 | struct device_node *child, *node = dev->of_node; |
453 | void __iomem *apb_base; |
454 | int ret; |
455 | |
456 | apb_base = devm_platform_ioremap_resource_byname(pdev, name: "apb"); |
457 | if (IS_ERR(ptr: apb_base)) |
458 | return PTR_ERR(ptr: apb_base); |
459 | |
460 | kirin_pcie->apb = devm_regmap_init_mmio(dev, apb_base, |
461 | &pcie_kirin_regmap_conf); |
462 | if (IS_ERR(ptr: kirin_pcie->apb)) |
463 | return PTR_ERR(ptr: kirin_pcie->apb); |
464 | |
465 | /* pcie internal PERST# gpio */ |
466 | kirin_pcie->gpio_id_dwc_perst = of_get_named_gpio(np: dev->of_node, |
467 | list_name: "reset-gpios", index: 0); |
468 | if (kirin_pcie->gpio_id_dwc_perst == -EPROBE_DEFER) { |
469 | return -EPROBE_DEFER; |
470 | } else if (!gpio_is_valid(number: kirin_pcie->gpio_id_dwc_perst)) { |
471 | dev_err(dev, "unable to get a valid gpio pin\n"); |
472 | return -ENODEV; |
473 | } |
474 | |
475 | ret = kirin_pcie_get_gpio_enable(pcie: kirin_pcie, pdev); |
476 | if (ret) |
477 | return ret; |
478 | |
479 | /* Parse OF children */ |
480 | for_each_available_child_of_node(node, child) { |
481 | ret = kirin_pcie_parse_port(pcie: kirin_pcie, pdev, node: child); |
482 | if (ret) |
483 | goto put_node; |
484 | } |
485 | |
486 | return 0; |
487 | |
488 | put_node: |
489 | of_node_put(node: child); |
490 | return ret; |
491 | } |
492 | |
493 | static void kirin_pcie_sideband_dbi_w_mode(struct kirin_pcie *kirin_pcie, |
494 | bool on) |
495 | { |
496 | u32 val; |
497 | |
498 | regmap_read(map: kirin_pcie->apb, SOC_PCIECTRL_CTRL0_ADDR, val: &val); |
499 | if (on) |
500 | val = val | PCIE_ELBI_SLV_DBI_ENABLE; |
501 | else |
502 | val = val & ~PCIE_ELBI_SLV_DBI_ENABLE; |
503 | |
504 | regmap_write(map: kirin_pcie->apb, SOC_PCIECTRL_CTRL0_ADDR, val); |
505 | } |
506 | |
507 | static void kirin_pcie_sideband_dbi_r_mode(struct kirin_pcie *kirin_pcie, |
508 | bool on) |
509 | { |
510 | u32 val; |
511 | |
512 | regmap_read(map: kirin_pcie->apb, SOC_PCIECTRL_CTRL1_ADDR, val: &val); |
513 | if (on) |
514 | val = val | PCIE_ELBI_SLV_DBI_ENABLE; |
515 | else |
516 | val = val & ~PCIE_ELBI_SLV_DBI_ENABLE; |
517 | |
518 | regmap_write(map: kirin_pcie->apb, SOC_PCIECTRL_CTRL1_ADDR, val); |
519 | } |
520 | |
521 | static int kirin_pcie_rd_own_conf(struct pci_bus *bus, unsigned int devfn, |
522 | int where, int size, u32 *val) |
523 | { |
524 | struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); |
525 | |
526 | if (PCI_SLOT(devfn)) |
527 | return PCIBIOS_DEVICE_NOT_FOUND; |
528 | |
529 | *val = dw_pcie_read_dbi(pci, reg: where, size); |
530 | return PCIBIOS_SUCCESSFUL; |
531 | } |
532 | |
533 | static int kirin_pcie_wr_own_conf(struct pci_bus *bus, unsigned int devfn, |
534 | int where, int size, u32 val) |
535 | { |
536 | struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); |
537 | |
538 | if (PCI_SLOT(devfn)) |
539 | return PCIBIOS_DEVICE_NOT_FOUND; |
540 | |
541 | dw_pcie_write_dbi(pci, reg: where, size, val); |
542 | return PCIBIOS_SUCCESSFUL; |
543 | } |
544 | |
545 | static int kirin_pcie_add_bus(struct pci_bus *bus) |
546 | { |
547 | struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); |
548 | struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); |
549 | int i, ret; |
550 | |
551 | if (!kirin_pcie->num_slots) |
552 | return 0; |
553 | |
554 | /* Send PERST# to each slot */ |
555 | for (i = 0; i < kirin_pcie->num_slots; i++) { |
556 | ret = gpio_direction_output(gpio: kirin_pcie->gpio_id_reset[i], value: 1); |
557 | if (ret) { |
558 | dev_err(pci->dev, "PERST# %s error: %d\n", |
559 | kirin_pcie->reset_names[i], ret); |
560 | } |
561 | } |
562 | usleep_range(PERST_2_ACCESS_MIN, PERST_2_ACCESS_MAX); |
563 | |
564 | return 0; |
565 | } |
566 | |
567 | static struct pci_ops kirin_pci_ops = { |
568 | .read = kirin_pcie_rd_own_conf, |
569 | .write = kirin_pcie_wr_own_conf, |
570 | .add_bus = kirin_pcie_add_bus, |
571 | }; |
572 | |
573 | static u32 kirin_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, |
574 | u32 reg, size_t size) |
575 | { |
576 | struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); |
577 | u32 ret; |
578 | |
579 | kirin_pcie_sideband_dbi_r_mode(kirin_pcie, on: true); |
580 | dw_pcie_read(addr: base + reg, size, val: &ret); |
581 | kirin_pcie_sideband_dbi_r_mode(kirin_pcie, on: false); |
582 | |
583 | return ret; |
584 | } |
585 | |
586 | static void kirin_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, |
587 | u32 reg, size_t size, u32 val) |
588 | { |
589 | struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); |
590 | |
591 | kirin_pcie_sideband_dbi_w_mode(kirin_pcie, on: true); |
592 | dw_pcie_write(addr: base + reg, size, val); |
593 | kirin_pcie_sideband_dbi_w_mode(kirin_pcie, on: false); |
594 | } |
595 | |
596 | static int kirin_pcie_link_up(struct dw_pcie *pci) |
597 | { |
598 | struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); |
599 | u32 val; |
600 | |
601 | regmap_read(map: kirin_pcie->apb, PCIE_APB_PHY_STATUS0, val: &val); |
602 | if ((val & PCIE_LINKUP_ENABLE) == PCIE_LINKUP_ENABLE) |
603 | return 1; |
604 | |
605 | return 0; |
606 | } |
607 | |
608 | static int kirin_pcie_start_link(struct dw_pcie *pci) |
609 | { |
610 | struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); |
611 | |
612 | /* assert LTSSM enable */ |
613 | regmap_write(map: kirin_pcie->apb, PCIE_APP_LTSSM_ENABLE, |
614 | PCIE_LTSSM_ENABLE_BIT); |
615 | |
616 | return 0; |
617 | } |
618 | |
619 | static int kirin_pcie_host_init(struct dw_pcie_rp *pp) |
620 | { |
621 | pp->bridge->ops = &kirin_pci_ops; |
622 | |
623 | return 0; |
624 | } |
625 | |
626 | static int kirin_pcie_gpio_request(struct kirin_pcie *kirin_pcie, |
627 | struct device *dev) |
628 | { |
629 | int ret, i; |
630 | |
631 | for (i = 0; i < kirin_pcie->num_slots; i++) { |
632 | if (!gpio_is_valid(number: kirin_pcie->gpio_id_reset[i])) { |
633 | dev_err(dev, "unable to get a valid %s gpio\n", |
634 | kirin_pcie->reset_names[i]); |
635 | return -ENODEV; |
636 | } |
637 | |
638 | ret = devm_gpio_request(dev, gpio: kirin_pcie->gpio_id_reset[i], |
639 | label: kirin_pcie->reset_names[i]); |
640 | if (ret) |
641 | return ret; |
642 | } |
643 | |
644 | for (i = 0; i < kirin_pcie->n_gpio_clkreq; i++) { |
645 | if (!gpio_is_valid(number: kirin_pcie->gpio_id_clkreq[i])) { |
646 | dev_err(dev, "unable to get a valid %s gpio\n", |
647 | kirin_pcie->clkreq_names[i]); |
648 | return -ENODEV; |
649 | } |
650 | |
651 | ret = devm_gpio_request(dev, gpio: kirin_pcie->gpio_id_clkreq[i], |
652 | label: kirin_pcie->clkreq_names[i]); |
653 | if (ret) |
654 | return ret; |
655 | |
656 | ret = gpio_direction_output(gpio: kirin_pcie->gpio_id_clkreq[i], value: 0); |
657 | if (ret) |
658 | return ret; |
659 | } |
660 | |
661 | return 0; |
662 | } |
663 | |
664 | static const struct dw_pcie_ops kirin_dw_pcie_ops = { |
665 | .read_dbi = kirin_pcie_read_dbi, |
666 | .write_dbi = kirin_pcie_write_dbi, |
667 | .link_up = kirin_pcie_link_up, |
668 | .start_link = kirin_pcie_start_link, |
669 | }; |
670 | |
671 | static const struct dw_pcie_host_ops kirin_pcie_host_ops = { |
672 | .init = kirin_pcie_host_init, |
673 | }; |
674 | |
675 | static int kirin_pcie_power_off(struct kirin_pcie *kirin_pcie) |
676 | { |
677 | int i; |
678 | |
679 | if (kirin_pcie->type == PCIE_KIRIN_INTERNAL_PHY) |
680 | return hi3660_pcie_phy_power_off(pcie: kirin_pcie); |
681 | |
682 | for (i = 0; i < kirin_pcie->n_gpio_clkreq; i++) |
683 | gpio_direction_output(gpio: kirin_pcie->gpio_id_clkreq[i], value: 1); |
684 | |
685 | phy_power_off(phy: kirin_pcie->phy); |
686 | phy_exit(phy: kirin_pcie->phy); |
687 | |
688 | return 0; |
689 | } |
690 | |
691 | static int kirin_pcie_power_on(struct platform_device *pdev, |
692 | struct kirin_pcie *kirin_pcie) |
693 | { |
694 | struct device *dev = &pdev->dev; |
695 | int ret; |
696 | |
697 | if (kirin_pcie->type == PCIE_KIRIN_INTERNAL_PHY) { |
698 | ret = hi3660_pcie_phy_init(pdev, pcie: kirin_pcie); |
699 | if (ret) |
700 | return ret; |
701 | |
702 | ret = hi3660_pcie_phy_power_on(pcie: kirin_pcie); |
703 | if (ret) |
704 | return ret; |
705 | } else { |
706 | kirin_pcie->phy = devm_of_phy_get(dev, np: dev->of_node, NULL); |
707 | if (IS_ERR(ptr: kirin_pcie->phy)) |
708 | return PTR_ERR(ptr: kirin_pcie->phy); |
709 | |
710 | ret = kirin_pcie_gpio_request(kirin_pcie, dev); |
711 | if (ret) |
712 | return ret; |
713 | |
714 | ret = phy_init(phy: kirin_pcie->phy); |
715 | if (ret) |
716 | goto err; |
717 | |
718 | ret = phy_power_on(phy: kirin_pcie->phy); |
719 | if (ret) |
720 | goto err; |
721 | } |
722 | |
723 | /* perst assert Endpoint */ |
724 | usleep_range(REF_2_PERST_MIN, REF_2_PERST_MAX); |
725 | |
726 | if (!gpio_request(gpio: kirin_pcie->gpio_id_dwc_perst, label: "pcie_perst_bridge")) { |
727 | ret = gpio_direction_output(gpio: kirin_pcie->gpio_id_dwc_perst, value: 1); |
728 | if (ret) |
729 | goto err; |
730 | } |
731 | |
732 | usleep_range(PERST_2_ACCESS_MIN, PERST_2_ACCESS_MAX); |
733 | |
734 | return 0; |
735 | err: |
736 | kirin_pcie_power_off(kirin_pcie); |
737 | |
738 | return ret; |
739 | } |
740 | |
741 | static void kirin_pcie_remove(struct platform_device *pdev) |
742 | { |
743 | struct kirin_pcie *kirin_pcie = platform_get_drvdata(pdev); |
744 | |
745 | dw_pcie_host_deinit(pp: &kirin_pcie->pci->pp); |
746 | |
747 | kirin_pcie_power_off(kirin_pcie); |
748 | } |
749 | |
750 | struct kirin_pcie_data { |
751 | enum pcie_kirin_phy_type phy_type; |
752 | }; |
753 | |
754 | static const struct kirin_pcie_data kirin_960_data = { |
755 | .phy_type = PCIE_KIRIN_INTERNAL_PHY, |
756 | }; |
757 | |
758 | static const struct kirin_pcie_data kirin_970_data = { |
759 | .phy_type = PCIE_KIRIN_EXTERNAL_PHY, |
760 | }; |
761 | |
762 | static const struct of_device_id kirin_pcie_match[] = { |
763 | { .compatible = "hisilicon,kirin960-pcie", .data = &kirin_960_data }, |
764 | { .compatible = "hisilicon,kirin970-pcie", .data = &kirin_970_data }, |
765 | {}, |
766 | }; |
767 | |
768 | static int kirin_pcie_probe(struct platform_device *pdev) |
769 | { |
770 | struct device *dev = &pdev->dev; |
771 | const struct kirin_pcie_data *data; |
772 | struct kirin_pcie *kirin_pcie; |
773 | struct dw_pcie *pci; |
774 | int ret; |
775 | |
776 | if (!dev->of_node) { |
777 | dev_err(dev, "NULL node\n"); |
778 | return -EINVAL; |
779 | } |
780 | |
781 | data = of_device_get_match_data(dev); |
782 | if (!data) { |
783 | dev_err(dev, "OF data missing\n"); |
784 | return -EINVAL; |
785 | } |
786 | |
787 | kirin_pcie = devm_kzalloc(dev, size: sizeof(struct kirin_pcie), GFP_KERNEL); |
788 | if (!kirin_pcie) |
789 | return -ENOMEM; |
790 | |
791 | pci = devm_kzalloc(dev, size: sizeof(*pci), GFP_KERNEL); |
792 | if (!pci) |
793 | return -ENOMEM; |
794 | |
795 | pci->dev = dev; |
796 | pci->ops = &kirin_dw_pcie_ops; |
797 | pci->pp.ops = &kirin_pcie_host_ops; |
798 | kirin_pcie->pci = pci; |
799 | kirin_pcie->type = data->phy_type; |
800 | |
801 | ret = kirin_pcie_get_resource(kirin_pcie, pdev); |
802 | if (ret) |
803 | return ret; |
804 | |
805 | platform_set_drvdata(pdev, data: kirin_pcie); |
806 | |
807 | ret = kirin_pcie_power_on(pdev, kirin_pcie); |
808 | if (ret) |
809 | return ret; |
810 | |
811 | return dw_pcie_host_init(pp: &pci->pp); |
812 | } |
813 | |
814 | static struct platform_driver kirin_pcie_driver = { |
815 | .probe = kirin_pcie_probe, |
816 | .remove_new = kirin_pcie_remove, |
817 | .driver = { |
818 | .name = "kirin-pcie", |
819 | .of_match_table = kirin_pcie_match, |
820 | .suppress_bind_attrs = true, |
821 | }, |
822 | }; |
823 | module_platform_driver(kirin_pcie_driver); |
824 | |
825 | MODULE_DEVICE_TABLE(of, kirin_pcie_match); |
826 | MODULE_DESCRIPTION("PCIe host controller driver for Kirin Phone SoCs"); |
827 | MODULE_AUTHOR("Xiaowei Song <songxiaowei@huawei.com>"); |
828 | MODULE_LICENSE("GPL v2"); |
829 |
Definitions
- pcie_kirin_phy_type
- kirin_pcie
- hi3660_pcie_phy
- kirin_apb_phy_writel
- kirin_apb_phy_readl
- hi3660_pcie_phy_get_clk
- hi3660_pcie_phy_get_resource
- hi3660_pcie_phy_start
- hi3660_pcie_phy_oe_enable
- hi3660_pcie_phy_clk_ctrl
- hi3660_pcie_phy_power_on
- hi3660_pcie_phy_init
- hi3660_pcie_phy_power_off
- pcie_kirin_regmap_conf
- kirin_pcie_get_gpio_enable
- kirin_pcie_parse_port
- kirin_pcie_get_resource
- kirin_pcie_sideband_dbi_w_mode
- kirin_pcie_sideband_dbi_r_mode
- kirin_pcie_rd_own_conf
- kirin_pcie_wr_own_conf
- kirin_pcie_add_bus
- kirin_pci_ops
- kirin_pcie_read_dbi
- kirin_pcie_write_dbi
- kirin_pcie_link_up
- kirin_pcie_start_link
- kirin_pcie_host_init
- kirin_pcie_gpio_request
- kirin_dw_pcie_ops
- kirin_pcie_host_ops
- kirin_pcie_power_off
- kirin_pcie_power_on
- kirin_pcie_remove
- kirin_pcie_data
- kirin_960_data
- kirin_970_data
- kirin_pcie_match
- kirin_pcie_probe
Improve your Profiling and Debugging skills
Find out more