global: Migrate CONFIG_SYS_FSL* symbols to the CFG_SYS namespace
[platform/kernel/u-boot.git] / drivers / pci / pcie_uniphier.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * pcie_uniphier.c - Socionext UniPhier PCIe driver
4  * Copyright 2019-2021 Socionext, Inc.
5  */
6
7 #include <clk.h>
8 #include <common.h>
9 #include <dm.h>
10 #include <dm/device_compat.h>
11 #include <generic-phy.h>
12 #include <linux/bitfield.h>
13 #include <linux/bitops.h>
14 #include <linux/compat.h>
15 #include <linux/delay.h>
16 #include <linux/io.h>
17 #include <pci.h>
18 #include <reset.h>
19
20 DECLARE_GLOBAL_DATA_PTR;
21
22 /* DBI registers */
23 #define PCIE_LINK_STATUS_REG            0x0080
24 #define PCIE_LINK_STATUS_WIDTH_MASK     GENMASK(25, 20)
25 #define PCIE_LINK_STATUS_SPEED_MASK     GENMASK(19, 16)
26
27 #define PCIE_MISC_CONTROL_1_OFF         0x08BC
28 #define PCIE_DBI_RO_WR_EN               BIT(0)
29
30 /* DBI iATU registers */
31 #define PCIE_ATU_VIEWPORT               0x0900
32 #define PCIE_ATU_REGION_INBOUND         BIT(31)
33 #define PCIE_ATU_REGION_OUTBOUND        0
34 #define PCIE_ATU_REGION_INDEX_MASK      GENMASK(3, 0)
35
36 #define PCIE_ATU_CR1                    0x0904
37 #define PCIE_ATU_TYPE_MEM               0
38 #define PCIE_ATU_TYPE_IO                2
39 #define PCIE_ATU_TYPE_CFG0              4
40 #define PCIE_ATU_TYPE_CFG1              5
41
42 #define PCIE_ATU_CR2                    0x0908
43 #define PCIE_ATU_ENABLE                 BIT(31)
44 #define PCIE_ATU_MATCH_MODE             BIT(30)
45 #define PCIE_ATU_BAR_NUM_MASK           GENMASK(10, 8)
46
47 #define PCIE_ATU_LOWER_BASE             0x090C
48 #define PCIE_ATU_UPPER_BASE             0x0910
49 #define PCIE_ATU_LIMIT                  0x0914
50 #define PCIE_ATU_LOWER_TARGET           0x0918
51 #define PCIE_ATU_BUS(x)                 FIELD_PREP(GENMASK(31, 24), x)
52 #define PCIE_ATU_DEV(x)                 FIELD_PREP(GENMASK(23, 19), x)
53 #define PCIE_ATU_FUNC(x)                FIELD_PREP(GENMASK(18, 16), x)
54 #define PCIE_ATU_UPPER_TARGET           0x091C
55
56 /* Link Glue registers */
57 #define PCL_PINCTRL0                    0x002c
58 #define PCL_PERST_PLDN_REGEN            BIT(12)
59 #define PCL_PERST_NOE_REGEN             BIT(11)
60 #define PCL_PERST_OUT_REGEN             BIT(8)
61 #define PCL_PERST_PLDN_REGVAL           BIT(4)
62 #define PCL_PERST_NOE_REGVAL            BIT(3)
63 #define PCL_PERST_OUT_REGVAL            BIT(0)
64
65 #define PCL_MODE                        0x8000
66 #define PCL_MODE_REGEN                  BIT(8)
67 #define PCL_MODE_REGVAL                 BIT(0)
68
69 #define PCL_APP_READY_CTRL              0x8008
70 #define PCL_APP_LTSSM_ENABLE            BIT(0)
71
72 #define PCL_APP_PM0                     0x8078
73 #define PCL_SYS_AUX_PWR_DET             BIT(8)
74
75 #define PCL_STATUS_LINK                 0x8140
76 #define PCL_RDLH_LINK_UP                BIT(1)
77 #define PCL_XMLH_LINK_UP                BIT(0)
78
79 #define LINK_UP_TIMEOUT_MS              100
80
81 struct uniphier_pcie_priv {
82         void *base;
83         void *dbi_base;
84         void *cfg_base;
85         fdt_size_t cfg_size;
86         struct fdt_resource link_res;
87         struct fdt_resource dbi_res;
88         struct fdt_resource cfg_res;
89
90         struct clk clk;
91         struct reset_ctl rst;
92         struct phy phy;
93
94         struct pci_region io;
95         struct pci_region mem;
96 };
97
98 static int pcie_dw_get_link_speed(struct uniphier_pcie_priv *priv)
99 {
100         u32 val = readl(priv->dbi_base + PCIE_LINK_STATUS_REG);
101
102         return FIELD_GET(PCIE_LINK_STATUS_SPEED_MASK, val);
103 }
104
105 static int pcie_dw_get_link_width(struct uniphier_pcie_priv *priv)
106 {
107         u32 val = readl(priv->dbi_base + PCIE_LINK_STATUS_REG);
108
109         return FIELD_GET(PCIE_LINK_STATUS_WIDTH_MASK, val);
110 }
111
112 static void pcie_dw_prog_outbound_atu(struct uniphier_pcie_priv *priv,
113                                       int index, int type, u64 cpu_addr,
114                                       u64 pci_addr, u32 size)
115 {
116         writel(PCIE_ATU_REGION_OUTBOUND
117                | FIELD_PREP(PCIE_ATU_REGION_INDEX_MASK, index),
118                priv->dbi_base + PCIE_ATU_VIEWPORT);
119         writel(lower_32_bits(cpu_addr),
120                priv->dbi_base + PCIE_ATU_LOWER_BASE);
121         writel(upper_32_bits(cpu_addr),
122                priv->dbi_base + PCIE_ATU_UPPER_BASE);
123         writel(lower_32_bits(cpu_addr + size - 1),
124                priv->dbi_base + PCIE_ATU_LIMIT);
125         writel(lower_32_bits(pci_addr),
126                priv->dbi_base + PCIE_ATU_LOWER_TARGET);
127         writel(upper_32_bits(pci_addr),
128                priv->dbi_base + PCIE_ATU_UPPER_TARGET);
129
130         writel(type, priv->dbi_base + PCIE_ATU_CR1);
131         writel(PCIE_ATU_ENABLE, priv->dbi_base + PCIE_ATU_CR2);
132 }
133
134 static int uniphier_pcie_addr_valid(pci_dev_t bdf, int first_busno)
135 {
136         /* accept only device {0,1} on first bus */
137         if ((PCI_BUS(bdf) != first_busno) || (PCI_DEV(bdf) > 1))
138                 return -EINVAL;
139
140         return 0;
141 }
142
143 static int uniphier_pcie_conf_address(const struct udevice *dev, pci_dev_t bdf,
144                                       uint offset, void **paddr)
145 {
146         struct uniphier_pcie_priv *priv = dev_get_priv(dev);
147         u32 busdev;
148         int seq = dev_seq(dev);
149         int ret;
150
151         ret = uniphier_pcie_addr_valid(bdf, seq);
152         if (ret)
153                 return ret;
154
155         if ((PCI_BUS(bdf) == seq) && !PCI_DEV(bdf)) {
156                 *paddr = (void *)(priv->dbi_base + offset);
157                 return 0;
158         }
159
160         busdev = PCIE_ATU_BUS(PCI_BUS(bdf) - seq)
161                 | PCIE_ATU_DEV(PCI_DEV(bdf))
162                 | PCIE_ATU_FUNC(PCI_FUNC(bdf));
163
164         pcie_dw_prog_outbound_atu(priv, 0,
165                                   PCIE_ATU_TYPE_CFG0, (u64)priv->cfg_base,
166                                   busdev, priv->cfg_size);
167         *paddr = (void *)(priv->cfg_base + offset);
168
169         return 0;
170 }
171
172 static int uniphier_pcie_read_config(const struct udevice *dev, pci_dev_t bdf,
173                                      uint offset, ulong *valp,
174                                      enum pci_size_t size)
175 {
176         return pci_generic_mmap_read_config(dev, uniphier_pcie_conf_address,
177                                             bdf, offset, valp, size);
178 }
179
180 static int uniphier_pcie_write_config(struct udevice *dev, pci_dev_t bdf,
181                                       uint offset, ulong val,
182                                       enum pci_size_t size)
183 {
184         return pci_generic_mmap_write_config(dev, uniphier_pcie_conf_address,
185                                              bdf, offset, val, size);
186 }
187
188 static void uniphier_pcie_ltssm_enable(struct uniphier_pcie_priv *priv,
189                                        bool enable)
190 {
191         u32 val;
192
193         val = readl(priv->base + PCL_APP_READY_CTRL);
194         if (enable)
195                 val |= PCL_APP_LTSSM_ENABLE;
196         else
197                 val &= ~PCL_APP_LTSSM_ENABLE;
198         writel(val, priv->base + PCL_APP_READY_CTRL);
199 }
200
201 static int uniphier_pcie_link_up(struct uniphier_pcie_priv *priv)
202 {
203         u32 val, mask;
204
205         val = readl(priv->base + PCL_STATUS_LINK);
206         mask = PCL_RDLH_LINK_UP | PCL_XMLH_LINK_UP;
207
208         return (val & mask) == mask;
209 }
210
211 static int uniphier_pcie_wait_link(struct uniphier_pcie_priv *priv)
212 {
213         unsigned long timeout;
214
215         timeout = get_timer(0) + LINK_UP_TIMEOUT_MS;
216
217         while (get_timer(0) < timeout) {
218                 if (uniphier_pcie_link_up(priv))
219                         return 0;
220         }
221
222         return -ETIMEDOUT;
223 }
224
225 static int uniphier_pcie_establish_link(struct uniphier_pcie_priv *priv)
226 {
227         if (uniphier_pcie_link_up(priv))
228                 return 0;
229
230         uniphier_pcie_ltssm_enable(priv, true);
231
232         return uniphier_pcie_wait_link(priv);
233 }
234
235 static void uniphier_pcie_init_rc(struct uniphier_pcie_priv *priv)
236 {
237         u32 val;
238
239         /* set RC mode */
240         val = readl(priv->base + PCL_MODE);
241         val |= PCL_MODE_REGEN;
242         val &= ~PCL_MODE_REGVAL;
243         writel(val, priv->base + PCL_MODE);
244
245         /* use auxiliary power detection */
246         val = readl(priv->base + PCL_APP_PM0);
247         val |= PCL_SYS_AUX_PWR_DET;
248         writel(val, priv->base + PCL_APP_PM0);
249
250         /* assert PERST# */
251         val = readl(priv->base + PCL_PINCTRL0);
252         val &= ~(PCL_PERST_NOE_REGVAL | PCL_PERST_OUT_REGVAL
253                  | PCL_PERST_PLDN_REGVAL);
254         val |= PCL_PERST_NOE_REGEN | PCL_PERST_OUT_REGEN
255                 | PCL_PERST_PLDN_REGEN;
256         writel(val, priv->base + PCL_PINCTRL0);
257
258         uniphier_pcie_ltssm_enable(priv, false);
259
260         mdelay(100);
261
262         /* deassert PERST# */
263         val = readl(priv->base + PCL_PINCTRL0);
264         val |= PCL_PERST_OUT_REGVAL | PCL_PERST_OUT_REGEN;
265         writel(val, priv->base + PCL_PINCTRL0);
266 }
267
268 static void uniphier_pcie_setup_rc(struct uniphier_pcie_priv *priv,
269                                    struct pci_controller *hose)
270 {
271         /* Store the IO and MEM windows settings for future use by the ATU */
272         priv->io.phys_start  = hose->regions[0].phys_start; /* IO base */
273         priv->io.bus_start   = hose->regions[0].bus_start;  /* IO_bus_addr */
274         priv->io.size        = hose->regions[0].size;       /* IO size */
275         priv->mem.phys_start = hose->regions[1].phys_start; /* MEM base */
276         priv->mem.bus_start  = hose->regions[1].bus_start;  /* MEM_bus_addr */
277         priv->mem.size       = hose->regions[1].size;       /* MEM size */
278
279         /* outbound: IO */
280         pcie_dw_prog_outbound_atu(priv, 0,
281                                   PCIE_ATU_TYPE_IO, priv->io.phys_start,
282                                   priv->io.bus_start, priv->io.size);
283
284         /* outbound: MEM */
285         pcie_dw_prog_outbound_atu(priv, 1,
286                                   PCIE_ATU_TYPE_MEM, priv->mem.phys_start,
287                                   priv->mem.bus_start, priv->mem.size);
288 }
289
290 static int uniphier_pcie_probe(struct udevice *dev)
291 {
292         struct uniphier_pcie_priv *priv = dev_get_priv(dev);
293         struct udevice *ctlr = pci_get_controller(dev);
294         struct pci_controller *hose = dev_get_uclass_priv(ctlr);
295         int ret;
296
297         priv->base = map_physmem(priv->link_res.start,
298                                  fdt_resource_size(&priv->link_res),
299                                  MAP_NOCACHE);
300         priv->dbi_base = map_physmem(priv->dbi_res.start,
301                                      fdt_resource_size(&priv->dbi_res),
302                                      MAP_NOCACHE);
303         priv->cfg_size = fdt_resource_size(&priv->cfg_res);
304         priv->cfg_base = map_physmem(priv->cfg_res.start,
305                                      priv->cfg_size, MAP_NOCACHE);
306
307         ret = clk_enable(&priv->clk);
308         if (ret) {
309                 dev_err(dev, "Failed to enable clk: %d\n", ret);
310                 return ret;
311         }
312         ret = reset_deassert(&priv->rst);
313         if (ret) {
314                 dev_err(dev, "Failed to deassert reset: %d\n", ret);
315                 goto out_clk_release;
316         }
317
318         ret = generic_phy_init(&priv->phy);
319         if (ret) {
320                 dev_err(dev, "Failed to initialize phy: %d\n", ret);
321                 goto out_reset_release;
322         }
323
324         ret = generic_phy_power_on(&priv->phy);
325         if (ret) {
326                 dev_err(dev, "Failed to power on phy: %d\n", ret);
327                 goto out_phy_exit;
328         }
329
330         uniphier_pcie_init_rc(priv);
331
332         /* set DBI to read only */
333         writel(0, priv->dbi_base + PCIE_MISC_CONTROL_1_OFF);
334
335         uniphier_pcie_setup_rc(priv, hose);
336
337         if (uniphier_pcie_establish_link(priv)) {
338                 printf("PCIE-%d: Link down\n", dev_seq(dev));
339         } else {
340                 printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n",
341                        dev_seq(dev), pcie_dw_get_link_speed(priv),
342                        pcie_dw_get_link_width(priv), hose->first_busno);
343         }
344
345         return 0;
346
347 out_phy_exit:
348         generic_phy_exit(&priv->phy);
349 out_reset_release:
350         reset_release_all(&priv->rst, 1);
351 out_clk_release:
352         clk_release_all(&priv->clk, 1);
353
354         return ret;
355 }
356
357 static int uniphier_pcie_of_to_plat(struct udevice *dev)
358 {
359         struct uniphier_pcie_priv *priv = dev_get_priv(dev);
360         const void *fdt = gd->fdt_blob;
361         int node = dev_of_offset(dev);
362         int ret;
363
364         ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
365                                      "link", &priv->link_res);
366         if (ret) {
367                 dev_err(dev, "Failed to get link regs: %d\n", ret);
368                 return ret;
369         }
370
371         ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
372                                      "dbi", &priv->dbi_res);
373         if (ret) {
374                 dev_err(dev, "Failed to get dbi regs: %d\n", ret);
375                 return ret;
376         }
377
378         ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
379                                      "config", &priv->cfg_res);
380         if (ret) {
381                 dev_err(dev, "Failed to get config regs: %d\n", ret);
382                 return ret;
383         }
384
385         ret = clk_get_by_index(dev, 0, &priv->clk);
386         if (ret) {
387                 dev_err(dev, "Failed to get clocks property: %d\n", ret);
388                 return ret;
389         }
390
391         ret = reset_get_by_index(dev, 0, &priv->rst);
392         if (ret) {
393                 dev_err(dev, "Failed to get resets property: %d\n", ret);
394                 return ret;
395         }
396
397         ret = generic_phy_get_by_index(dev, 0, &priv->phy);
398         if (ret) {
399                 dev_err(dev, "Failed to get phy property: %d\n", ret);
400                 return ret;
401         }
402
403         return 0;
404 }
405
406 static const struct dm_pci_ops uniphier_pcie_ops = {
407         .read_config    = uniphier_pcie_read_config,
408         .write_config   = uniphier_pcie_write_config,
409 };
410
411 static const struct udevice_id uniphier_pcie_ids[] = {
412         { .compatible = "socionext,uniphier-pcie", },
413         { /* Sentinel */ }
414 };
415
416 U_BOOT_DRIVER(pcie_uniphier) = {
417         .name     = "uniphier-pcie",
418         .id       = UCLASS_PCI,
419         .of_match = uniphier_pcie_ids,
420         .probe    = uniphier_pcie_probe,
421         .ops      = &uniphier_pcie_ops,
422         .of_to_plat = uniphier_pcie_of_to_plat,
423         .priv_auto = sizeof(struct uniphier_pcie_priv),
424 };