aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/controller/dwc/pcie-histb.c
diff options
context:
space:
mode:
authorShawn Lin <shawn.lin@rock-chips.com>2018-05-30 21:12:37 -0400
committerBjorn Helgaas <bhelgaas@google.com>2018-06-08 08:50:11 -0400
commit6e0832fa432ec99c94caee733c8f5851cf85560b (patch)
treec4326f9e2d8ff1a6cb17e959fc5268c9e577ca94 /drivers/pci/controller/dwc/pcie-histb.c
parent3a3869f1c443383ef8354ffa0e5fb8df65d8b549 (diff)
PCI: Collect all native drivers under drivers/pci/controller/
Native PCI drivers for root complex devices were originally all in drivers/pci/host/. Some of these devices can also be operated in endpoint mode. Drivers for endpoint mode didn't seem to fit in the "host" directory, so we put both the root complex and endpoint drivers in per-device directories, e.g., drivers/pci/dwc/, drivers/pci/cadence/, etc. These per-device directories contain trivial Kconfig and Makefiles and clutter drivers/pci/. Make a new drivers/pci/controllers/ directory and collect all the device-specific drivers there. No functional change intended. Link: https://lkml.kernel.org/r/1520304202-232891-1-git-send-email-shawn.lin@rock-chips.com Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> [bhelgaas: changelog] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/controller/dwc/pcie-histb.c')
-rw-r--r--drivers/pci/controller/dwc/pcie-histb.c472
1 files changed, 472 insertions, 0 deletions
diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c
new file mode 100644
index 000000000000..3611d6ce9a92
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-histb.c
@@ -0,0 +1,472 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * PCIe host controller driver for HiSilicon STB SoCs
4 *
5 * Copyright (C) 2016-2017 HiSilicon Co., Ltd. http://www.hisilicon.com
6 *
7 * Authors: Ruqiang Ju <juruqiang@hisilicon.com>
8 * Jianguo Sun <sunjianguo1@huawei.com>
9 */
10
11#include <linux/clk.h>
12#include <linux/delay.h>
13#include <linux/interrupt.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/of_gpio.h>
18#include <linux/pci.h>
19#include <linux/phy/phy.h>
20#include <linux/platform_device.h>
21#include <linux/resource.h>
22#include <linux/reset.h>
23
24#include "pcie-designware.h"
25
26#define to_histb_pcie(x) dev_get_drvdata((x)->dev)
27
28#define PCIE_SYS_CTRL0 0x0000
29#define PCIE_SYS_CTRL1 0x0004
30#define PCIE_SYS_CTRL7 0x001C
31#define PCIE_SYS_CTRL13 0x0034
32#define PCIE_SYS_CTRL15 0x003C
33#define PCIE_SYS_CTRL16 0x0040
34#define PCIE_SYS_CTRL17 0x0044
35
36#define PCIE_SYS_STAT0 0x0100
37#define PCIE_SYS_STAT4 0x0110
38
39#define PCIE_RDLH_LINK_UP BIT(5)
40#define PCIE_XMLH_LINK_UP BIT(15)
41#define PCIE_ELBI_SLV_DBI_ENABLE BIT(21)
42#define PCIE_APP_LTSSM_ENABLE BIT(11)
43
44#define PCIE_DEVICE_TYPE_MASK GENMASK(31, 28)
45#define PCIE_WM_EP 0
46#define PCIE_WM_LEGACY BIT(1)
47#define PCIE_WM_RC BIT(30)
48
49#define PCIE_LTSSM_STATE_MASK GENMASK(5, 0)
50#define PCIE_LTSSM_STATE_ACTIVE 0x11
51
52struct histb_pcie {
53 struct dw_pcie *pci;
54 struct clk *aux_clk;
55 struct clk *pipe_clk;
56 struct clk *sys_clk;
57 struct clk *bus_clk;
58 struct phy *phy;
59 struct reset_control *soft_reset;
60 struct reset_control *sys_reset;
61 struct reset_control *bus_reset;
62 void __iomem *ctrl;
63 int reset_gpio;
64 struct regulator *vpcie;
65};
66
67static u32 histb_pcie_readl(struct histb_pcie *histb_pcie, u32 reg)
68{
69 return readl(histb_pcie->ctrl + reg);
70}
71
72static void histb_pcie_writel(struct histb_pcie *histb_pcie, u32 reg, u32 val)
73{
74 writel(val, histb_pcie->ctrl + reg);
75}
76
77static void histb_pcie_dbi_w_mode(struct pcie_port *pp, bool enable)
78{
79 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
80 struct histb_pcie *hipcie = to_histb_pcie(pci);
81 u32 val;
82
83 val = histb_pcie_readl(hipcie, PCIE_SYS_CTRL0);
84 if (enable)
85 val |= PCIE_ELBI_SLV_DBI_ENABLE;
86 else
87 val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
88 histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, val);
89}
90
91static void histb_pcie_dbi_r_mode(struct pcie_port *pp, bool enable)
92{
93 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
94 struct histb_pcie *hipcie = to_histb_pcie(pci);
95 u32 val;
96
97 val = histb_pcie_readl(hipcie, PCIE_SYS_CTRL1);
98 if (enable)
99 val |= PCIE_ELBI_SLV_DBI_ENABLE;
100 else
101 val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
102 histb_pcie_writel(hipcie, PCIE_SYS_CTRL1, val);
103}
104
105static u32 histb_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base,
106 u32 reg, size_t size)
107{
108 u32 val;
109
110 histb_pcie_dbi_r_mode(&pci->pp, true);
111 dw_pcie_read(base + reg, size, &val);
112 histb_pcie_dbi_r_mode(&pci->pp, false);
113
114 return val;
115}
116
117static void histb_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base,
118 u32 reg, size_t size, u32 val)
119{
120 histb_pcie_dbi_w_mode(&pci->pp, true);
121 dw_pcie_write(base + reg, size, val);
122 histb_pcie_dbi_w_mode(&pci->pp, false);
123}
124
125static int histb_pcie_rd_own_conf(struct pcie_port *pp, int where,
126 int size, u32 *val)
127{
128 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
129 int ret;
130
131 histb_pcie_dbi_r_mode(pp, true);
132 ret = dw_pcie_read(pci->dbi_base + where, size, val);
133 histb_pcie_dbi_r_mode(pp, false);
134
135 return ret;
136}
137
138static int histb_pcie_wr_own_conf(struct pcie_port *pp, int where,
139 int size, u32 val)
140{
141 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
142 int ret;
143
144 histb_pcie_dbi_w_mode(pp, true);
145 ret = dw_pcie_write(pci->dbi_base + where, size, val);
146 histb_pcie_dbi_w_mode(pp, false);
147
148 return ret;
149}
150
151static int histb_pcie_link_up(struct dw_pcie *pci)
152{
153 struct histb_pcie *hipcie = to_histb_pcie(pci);
154 u32 regval;
155 u32 status;
156
157 regval = histb_pcie_readl(hipcie, PCIE_SYS_STAT0);
158 status = histb_pcie_readl(hipcie, PCIE_SYS_STAT4);
159 status &= PCIE_LTSSM_STATE_MASK;
160 if ((regval & PCIE_XMLH_LINK_UP) && (regval & PCIE_RDLH_LINK_UP) &&
161 (status == PCIE_LTSSM_STATE_ACTIVE))
162 return 1;
163
164 return 0;
165}
166
167static int histb_pcie_establish_link(struct pcie_port *pp)
168{
169 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
170 struct histb_pcie *hipcie = to_histb_pcie(pci);
171 u32 regval;
172
173 if (dw_pcie_link_up(pci)) {
174 dev_info(pci->dev, "Link already up\n");
175 return 0;
176 }
177
178 /* PCIe RC work mode */
179 regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL0);
180 regval &= ~PCIE_DEVICE_TYPE_MASK;
181 regval |= PCIE_WM_RC;
182 histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, regval);
183
184 /* setup root complex */
185 dw_pcie_setup_rc(pp);
186
187 /* assert LTSSM enable */
188 regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL7);
189 regval |= PCIE_APP_LTSSM_ENABLE;
190 histb_pcie_writel(hipcie, PCIE_SYS_CTRL7, regval);
191
192 return dw_pcie_wait_for_link(pci);
193}
194
195static int histb_pcie_host_init(struct pcie_port *pp)
196{
197 histb_pcie_establish_link(pp);
198
199 if (IS_ENABLED(CONFIG_PCI_MSI))
200 dw_pcie_msi_init(pp);
201
202 return 0;
203}
204
205static struct dw_pcie_host_ops histb_pcie_host_ops = {
206 .rd_own_conf = histb_pcie_rd_own_conf,
207 .wr_own_conf = histb_pcie_wr_own_conf,
208 .host_init = histb_pcie_host_init,
209};
210
211static void histb_pcie_host_disable(struct histb_pcie *hipcie)
212{
213 reset_control_assert(hipcie->soft_reset);
214 reset_control_assert(hipcie->sys_reset);
215 reset_control_assert(hipcie->bus_reset);
216
217 clk_disable_unprepare(hipcie->aux_clk);
218 clk_disable_unprepare(hipcie->pipe_clk);
219 clk_disable_unprepare(hipcie->sys_clk);
220 clk_disable_unprepare(hipcie->bus_clk);
221
222 if (gpio_is_valid(hipcie->reset_gpio))
223 gpio_set_value_cansleep(hipcie->reset_gpio, 0);
224
225 if (hipcie->vpcie)
226 regulator_disable(hipcie->vpcie);
227}
228
229static int histb_pcie_host_enable(struct pcie_port *pp)
230{
231 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
232 struct histb_pcie *hipcie = to_histb_pcie(pci);
233 struct device *dev = pci->dev;
234 int ret;
235
236 /* power on PCIe device if have */
237 if (hipcie->vpcie) {
238 ret = regulator_enable(hipcie->vpcie);
239 if (ret) {
240 dev_err(dev, "failed to enable regulator: %d\n", ret);
241 return ret;
242 }
243 }
244
245 if (gpio_is_valid(hipcie->reset_gpio))
246 gpio_set_value_cansleep(hipcie->reset_gpio, 1);
247
248 ret = clk_prepare_enable(hipcie->bus_clk);
249 if (ret) {
250 dev_err(dev, "cannot prepare/enable bus clk\n");
251 goto err_bus_clk;
252 }
253
254 ret = clk_prepare_enable(hipcie->sys_clk);
255 if (ret) {
256 dev_err(dev, "cannot prepare/enable sys clk\n");
257 goto err_sys_clk;
258 }
259
260 ret = clk_prepare_enable(hipcie->pipe_clk);
261 if (ret) {
262 dev_err(dev, "cannot prepare/enable pipe clk\n");
263 goto err_pipe_clk;
264 }
265
266 ret = clk_prepare_enable(hipcie->aux_clk);
267 if (ret) {
268 dev_err(dev, "cannot prepare/enable aux clk\n");
269 goto err_aux_clk;
270 }
271
272 reset_control_assert(hipcie->soft_reset);
273 reset_control_deassert(hipcie->soft_reset);
274
275 reset_control_assert(hipcie->sys_reset);
276 reset_control_deassert(hipcie->sys_reset);
277
278 reset_control_assert(hipcie->bus_reset);
279 reset_control_deassert(hipcie->bus_reset);
280
281 return 0;
282
283err_aux_clk:
284 clk_disable_unprepare(hipcie->pipe_clk);
285err_pipe_clk:
286 clk_disable_unprepare(hipcie->sys_clk);
287err_sys_clk:
288 clk_disable_unprepare(hipcie->bus_clk);
289err_bus_clk:
290 if (hipcie->vpcie)
291 regulator_disable(hipcie->vpcie);
292
293 return ret;
294}
295
296static const struct dw_pcie_ops dw_pcie_ops = {
297 .read_dbi = histb_pcie_read_dbi,
298 .write_dbi = histb_pcie_write_dbi,
299 .link_up = histb_pcie_link_up,
300};
301
302static int histb_pcie_probe(struct platform_device *pdev)
303{
304 struct histb_pcie *hipcie;
305 struct dw_pcie *pci;
306 struct pcie_port *pp;
307 struct resource *res;
308 struct device_node *np = pdev->dev.of_node;
309 struct device *dev = &pdev->dev;
310 enum of_gpio_flags of_flags;
311 unsigned long flag = GPIOF_DIR_OUT;
312 int ret;
313
314 hipcie = devm_kzalloc(dev, sizeof(*hipcie), GFP_KERNEL);
315 if (!hipcie)
316 return -ENOMEM;
317
318 pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
319 if (!pci)
320 return -ENOMEM;
321
322 hipcie->pci = pci;
323 pp = &pci->pp;
324 pci->dev = dev;
325 pci->ops = &dw_pcie_ops;
326
327 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control");
328 hipcie->ctrl = devm_ioremap_resource(dev, res);
329 if (IS_ERR(hipcie->ctrl)) {
330 dev_err(dev, "cannot get control reg base\n");
331 return PTR_ERR(hipcie->ctrl);
332 }
333
334 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc-dbi");
335 pci->dbi_base = devm_ioremap_resource(dev, res);
336 if (IS_ERR(pci->dbi_base)) {
337 dev_err(dev, "cannot get rc-dbi base\n");
338 return PTR_ERR(pci->dbi_base);
339 }
340
341 hipcie->vpcie = devm_regulator_get_optional(dev, "vpcie");
342 if (IS_ERR(hipcie->vpcie)) {
343 if (PTR_ERR(hipcie->vpcie) == -EPROBE_DEFER)
344 return -EPROBE_DEFER;
345 hipcie->vpcie = NULL;
346 }
347
348 hipcie->reset_gpio = of_get_named_gpio_flags(np,
349 "reset-gpios", 0, &of_flags);
350 if (of_flags & OF_GPIO_ACTIVE_LOW)
351 flag |= GPIOF_ACTIVE_LOW;
352 if (gpio_is_valid(hipcie->reset_gpio)) {
353 ret = devm_gpio_request_one(dev, hipcie->reset_gpio,
354 flag, "PCIe device power control");
355 if (ret) {
356 dev_err(dev, "unable to request gpio\n");
357 return ret;
358 }
359 }
360
361 hipcie->aux_clk = devm_clk_get(dev, "aux");
362 if (IS_ERR(hipcie->aux_clk)) {
363 dev_err(dev, "Failed to get PCIe aux clk\n");
364 return PTR_ERR(hipcie->aux_clk);
365 }
366
367 hipcie->pipe_clk = devm_clk_get(dev, "pipe");
368 if (IS_ERR(hipcie->pipe_clk)) {
369 dev_err(dev, "Failed to get PCIe pipe clk\n");
370 return PTR_ERR(hipcie->pipe_clk);
371 }
372
373 hipcie->sys_clk = devm_clk_get(dev, "sys");
374 if (IS_ERR(hipcie->sys_clk)) {
375 dev_err(dev, "Failed to get PCIEe sys clk\n");
376 return PTR_ERR(hipcie->sys_clk);
377 }
378
379 hipcie->bus_clk = devm_clk_get(dev, "bus");
380 if (IS_ERR(hipcie->bus_clk)) {
381 dev_err(dev, "Failed to get PCIe bus clk\n");
382 return PTR_ERR(hipcie->bus_clk);
383 }
384
385 hipcie->soft_reset = devm_reset_control_get(dev, "soft");
386 if (IS_ERR(hipcie->soft_reset)) {
387 dev_err(dev, "couldn't get soft reset\n");
388 return PTR_ERR(hipcie->soft_reset);
389 }
390
391 hipcie->sys_reset = devm_reset_control_get(dev, "sys");
392 if (IS_ERR(hipcie->sys_reset)) {
393 dev_err(dev, "couldn't get sys reset\n");
394 return PTR_ERR(hipcie->sys_reset);
395 }
396
397 hipcie->bus_reset = devm_reset_control_get(dev, "bus");
398 if (IS_ERR(hipcie->bus_reset)) {
399 dev_err(dev, "couldn't get bus reset\n");
400 return PTR_ERR(hipcie->bus_reset);
401 }
402
403 if (IS_ENABLED(CONFIG_PCI_MSI)) {
404 pp->msi_irq = platform_get_irq_byname(pdev, "msi");
405 if (pp->msi_irq < 0) {
406 dev_err(dev, "Failed to get MSI IRQ\n");
407 return pp->msi_irq;
408 }
409 }
410
411 hipcie->phy = devm_phy_get(dev, "phy");
412 if (IS_ERR(hipcie->phy)) {
413 dev_info(dev, "no pcie-phy found\n");
414 hipcie->phy = NULL;
415 /* fall through here!
416 * if no pcie-phy found, phy init
417 * should be done under boot!
418 */
419 } else {
420 phy_init(hipcie->phy);
421 }
422
423 pp->root_bus_nr = -1;
424 pp->ops = &histb_pcie_host_ops;
425
426 platform_set_drvdata(pdev, hipcie);
427
428 ret = histb_pcie_host_enable(pp);
429 if (ret) {
430 dev_err(dev, "failed to enable host\n");
431 return ret;
432 }
433
434 ret = dw_pcie_host_init(pp);
435 if (ret) {
436 dev_err(dev, "failed to initialize host\n");
437 return ret;
438 }
439
440 return 0;
441}
442
443static int histb_pcie_remove(struct platform_device *pdev)
444{
445 struct histb_pcie *hipcie = platform_get_drvdata(pdev);
446
447 histb_pcie_host_disable(hipcie);
448
449 if (hipcie->phy)
450 phy_exit(hipcie->phy);
451
452 return 0;
453}
454
455static const struct of_device_id histb_pcie_of_match[] = {
456 { .compatible = "hisilicon,hi3798cv200-pcie", },
457 {},
458};
459MODULE_DEVICE_TABLE(of, histb_pcie_of_match);
460
461static struct platform_driver histb_pcie_platform_driver = {
462 .probe = histb_pcie_probe,
463 .remove = histb_pcie_remove,
464 .driver = {
465 .name = "histb-pcie",
466 .of_match_table = histb_pcie_of_match,
467 },
468};
469module_platform_driver(histb_pcie_platform_driver);
470
471MODULE_DESCRIPTION("HiSilicon STB PCIe host controller driver");
472MODULE_LICENSE("GPL v2");