Merge tag 'io_uring-5.15-2021-09-11' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / drivers / pci / controller / dwc / pcie-dw-rockchip.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * PCIe host controller driver for Rockchip SoCs.
4  *
5  * Copyright (C) 2021 Rockchip Electronics Co., Ltd.
6  *              http://www.rock-chips.com
7  *
8  * Author: Simon Xue <xxm@rock-chips.com>
9  */
10
11 #include <linux/clk.h>
12 #include <linux/gpio/consumer.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/module.h>
15 #include <linux/of_device.h>
16 #include <linux/phy/phy.h>
17 #include <linux/platform_device.h>
18 #include <linux/regmap.h>
19 #include <linux/reset.h>
20
21 #include "pcie-designware.h"
22
23 /*
24  * The upper 16 bits of PCIE_CLIENT_CONFIG are a write
25  * mask for the lower 16 bits.
26  */
27 #define HIWORD_UPDATE(mask, val) (((mask) << 16) | (val))
28 #define HIWORD_UPDATE_BIT(val)  HIWORD_UPDATE(val, val)
29
30 #define to_rockchip_pcie(x) dev_get_drvdata((x)->dev)
31
32 #define PCIE_CLIENT_RC_MODE             HIWORD_UPDATE_BIT(0x40)
33 #define PCIE_CLIENT_ENABLE_LTSSM        HIWORD_UPDATE_BIT(0xc)
34 #define PCIE_SMLH_LINKUP                BIT(16)
35 #define PCIE_RDLH_LINKUP                BIT(17)
36 #define PCIE_LINKUP                     (PCIE_SMLH_LINKUP | PCIE_RDLH_LINKUP)
37 #define PCIE_L0S_ENTRY                  0x11
38 #define PCIE_CLIENT_GENERAL_CONTROL     0x0
39 #define PCIE_CLIENT_GENERAL_DEBUG       0x104
40 #define PCIE_CLIENT_HOT_RESET_CTRL      0x180
41 #define PCIE_CLIENT_LTSSM_STATUS        0x300
42 #define PCIE_LTSSM_ENABLE_ENHANCE       BIT(4)
43 #define PCIE_LTSSM_STATUS_MASK          GENMASK(5, 0)
44
45 struct rockchip_pcie {
46         struct dw_pcie                  pci;
47         void __iomem                    *apb_base;
48         struct phy                      *phy;
49         struct clk_bulk_data            *clks;
50         unsigned int                    clk_cnt;
51         struct reset_control            *rst;
52         struct gpio_desc                *rst_gpio;
53         struct regulator                *vpcie3v3;
54 };
55
56 static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip,
57                                              u32 reg)
58 {
59         return readl_relaxed(rockchip->apb_base + reg);
60 }
61
62 static void rockchip_pcie_writel_apb(struct rockchip_pcie *rockchip,
63                                                 u32 val, u32 reg)
64 {
65         writel_relaxed(val, rockchip->apb_base + reg);
66 }
67
68 static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip)
69 {
70         rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_ENABLE_LTSSM,
71                                  PCIE_CLIENT_GENERAL_CONTROL);
72 }
73
74 static int rockchip_pcie_link_up(struct dw_pcie *pci)
75 {
76         struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
77         u32 val = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_LTSSM_STATUS);
78
79         if ((val & PCIE_LINKUP) == PCIE_LINKUP &&
80             (val & PCIE_LTSSM_STATUS_MASK) == PCIE_L0S_ENTRY)
81                 return 1;
82
83         return 0;
84 }
85
86 static int rockchip_pcie_start_link(struct dw_pcie *pci)
87 {
88         struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
89
90         /* Reset device */
91         gpiod_set_value_cansleep(rockchip->rst_gpio, 0);
92
93         rockchip_pcie_enable_ltssm(rockchip);
94
95         /*
96          * PCIe requires the refclk to be stable for 100µs prior to releasing
97          * PERST. See table 2-4 in section 2.6.2 AC Specifications of the PCI
98          * Express Card Electromechanical Specification, 1.1. However, we don't
99          * know if the refclk is coming from RC's PHY or external OSC. If it's
100          * from RC, so enabling LTSSM is the just right place to release #PERST.
101          * We need more extra time as before, rather than setting just
102          * 100us as we don't know how long should the device need to reset.
103          */
104         msleep(100);
105         gpiod_set_value_cansleep(rockchip->rst_gpio, 1);
106
107         return 0;
108 }
109
110 static int rockchip_pcie_host_init(struct pcie_port *pp)
111 {
112         struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
113         struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
114         u32 val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE);
115
116         /* LTSSM enable control mode */
117         rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL);
118
119         rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE,
120                                  PCIE_CLIENT_GENERAL_CONTROL);
121
122         return 0;
123 }
124
125 static const struct dw_pcie_host_ops rockchip_pcie_host_ops = {
126         .host_init = rockchip_pcie_host_init,
127 };
128
129 static int rockchip_pcie_clk_init(struct rockchip_pcie *rockchip)
130 {
131         struct device *dev = rockchip->pci.dev;
132         int ret;
133
134         ret = devm_clk_bulk_get_all(dev, &rockchip->clks);
135         if (ret < 0)
136                 return ret;
137
138         rockchip->clk_cnt = ret;
139
140         return clk_bulk_prepare_enable(rockchip->clk_cnt, rockchip->clks);
141 }
142
143 static int rockchip_pcie_resource_get(struct platform_device *pdev,
144                                       struct rockchip_pcie *rockchip)
145 {
146         rockchip->apb_base = devm_platform_ioremap_resource_byname(pdev, "apb");
147         if (IS_ERR(rockchip->apb_base))
148                 return PTR_ERR(rockchip->apb_base);
149
150         rockchip->rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset",
151                                                      GPIOD_OUT_HIGH);
152         if (IS_ERR(rockchip->rst_gpio))
153                 return PTR_ERR(rockchip->rst_gpio);
154
155         return 0;
156 }
157
158 static int rockchip_pcie_phy_init(struct rockchip_pcie *rockchip)
159 {
160         struct device *dev = rockchip->pci.dev;
161         int ret;
162
163         rockchip->phy = devm_phy_get(dev, "pcie-phy");
164         if (IS_ERR(rockchip->phy))
165                 return dev_err_probe(dev, PTR_ERR(rockchip->phy),
166                                      "missing PHY\n");
167
168         ret = phy_init(rockchip->phy);
169         if (ret < 0)
170                 return ret;
171
172         ret = phy_power_on(rockchip->phy);
173         if (ret)
174                 phy_exit(rockchip->phy);
175
176         return ret;
177 }
178
179 static void rockchip_pcie_phy_deinit(struct rockchip_pcie *rockchip)
180 {
181         phy_exit(rockchip->phy);
182         phy_power_off(rockchip->phy);
183 }
184
185 static int rockchip_pcie_reset_control_release(struct rockchip_pcie *rockchip)
186 {
187         struct device *dev = rockchip->pci.dev;
188
189         rockchip->rst = devm_reset_control_array_get_exclusive(dev);
190         if (IS_ERR(rockchip->rst))
191                 return dev_err_probe(dev, PTR_ERR(rockchip->rst),
192                                      "failed to get reset lines\n");
193
194         return reset_control_deassert(rockchip->rst);
195 }
196
197 static const struct dw_pcie_ops dw_pcie_ops = {
198         .link_up = rockchip_pcie_link_up,
199         .start_link = rockchip_pcie_start_link,
200 };
201
202 static int rockchip_pcie_probe(struct platform_device *pdev)
203 {
204         struct device *dev = &pdev->dev;
205         struct rockchip_pcie *rockchip;
206         struct pcie_port *pp;
207         int ret;
208
209         rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL);
210         if (!rockchip)
211                 return -ENOMEM;
212
213         platform_set_drvdata(pdev, rockchip);
214
215         rockchip->pci.dev = dev;
216         rockchip->pci.ops = &dw_pcie_ops;
217
218         pp = &rockchip->pci.pp;
219         pp->ops = &rockchip_pcie_host_ops;
220
221         ret = rockchip_pcie_resource_get(pdev, rockchip);
222         if (ret)
223                 return ret;
224
225         /* DON'T MOVE ME: must be enable before PHY init */
226         rockchip->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3");
227         if (IS_ERR(rockchip->vpcie3v3)) {
228                 if (PTR_ERR(rockchip->vpcie3v3) != -ENODEV)
229                         return dev_err_probe(dev, PTR_ERR(rockchip->vpcie3v3),
230                                         "failed to get vpcie3v3 regulator\n");
231                 rockchip->vpcie3v3 = NULL;
232         } else {
233                 ret = regulator_enable(rockchip->vpcie3v3);
234                 if (ret) {
235                         dev_err(dev, "failed to enable vpcie3v3 regulator\n");
236                         return ret;
237                 }
238         }
239
240         ret = rockchip_pcie_phy_init(rockchip);
241         if (ret)
242                 goto disable_regulator;
243
244         ret = rockchip_pcie_reset_control_release(rockchip);
245         if (ret)
246                 goto deinit_phy;
247
248         ret = rockchip_pcie_clk_init(rockchip);
249         if (ret)
250                 goto deinit_phy;
251
252         ret = dw_pcie_host_init(pp);
253         if (!ret)
254                 return 0;
255
256         clk_bulk_disable_unprepare(rockchip->clk_cnt, rockchip->clks);
257 deinit_phy:
258         rockchip_pcie_phy_deinit(rockchip);
259 disable_regulator:
260         if (rockchip->vpcie3v3)
261                 regulator_disable(rockchip->vpcie3v3);
262
263         return ret;
264 }
265
266 static const struct of_device_id rockchip_pcie_of_match[] = {
267         { .compatible = "rockchip,rk3568-pcie", },
268         {},
269 };
270
271 static struct platform_driver rockchip_pcie_driver = {
272         .driver = {
273                 .name   = "rockchip-dw-pcie",
274                 .of_match_table = rockchip_pcie_of_match,
275                 .suppress_bind_attrs = true,
276         },
277         .probe = rockchip_pcie_probe,
278 };
279 builtin_platform_driver(rockchip_pcie_driver);