blob: 33a5c3cc208bae292ee7fbdc8fd2ccd6a3814403 [file] [log] [blame]
Sekhar Nori18db23d2019-08-01 19:12:57 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018 Texas Instruments, Inc
4 */
5
6#include <common.h>
7#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -06008#include <log.h>
Sekhar Nori18db23d2019-08-01 19:12:57 +05309#include <pci.h>
10#include <generic-phy.h>
11#include <power-domain.h>
12#include <regmap.h>
13#include <syscon.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060014#include <asm/global_data.h>
Sekhar Nori18db23d2019-08-01 19:12:57 +053015#include <asm/io.h>
16#include <asm-generic/gpio.h>
Simon Glass9bc15642020-02-03 07:36:16 -070017#include <dm/device_compat.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060018#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060019#include <linux/delay.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070020#include <linux/err.h>
Sekhar Nori18db23d2019-08-01 19:12:57 +053021
22DECLARE_GLOBAL_DATA_PTR;
23
24#define PCIE_VENDORID_MASK GENMASK(15, 0)
25#define PCIE_DEVICEID_SHIFT 16
26
27/* PCI DBICS registers */
28#define PCIE_CONFIG_BAR0 0x10
29#define PCIE_LINK_STATUS_REG 0x80
30#define PCIE_LINK_STATUS_SPEED_OFF 16
31#define PCIE_LINK_STATUS_SPEED_MASK (0xf << PCIE_LINK_STATUS_SPEED_OFF)
32#define PCIE_LINK_STATUS_WIDTH_OFF 20
33#define PCIE_LINK_STATUS_WIDTH_MASK (0xf << PCIE_LINK_STATUS_WIDTH_OFF)
34
35#define PCIE_LINK_CAPABILITY 0x7c
36#define PCIE_LINK_CTL_2 0xa0
37#define TARGET_LINK_SPEED_MASK 0xf
38#define LINK_SPEED_GEN_1 0x1
39#define LINK_SPEED_GEN_2 0x2
40#define LINK_SPEED_GEN_3 0x3
41
42#define PCIE_MISC_CONTROL_1_OFF 0x8bc
43#define PCIE_DBI_RO_WR_EN BIT(0)
44
45#define PLR_OFFSET 0x700
46#define PCIE_PORT_DEBUG0 (PLR_OFFSET + 0x28)
47#define PORT_LOGIC_LTSSM_STATE_MASK 0x1f
48#define PORT_LOGIC_LTSSM_STATE_L0 0x11
49
50#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80c
51#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
52
53#define PCIE_LINK_UP_TIMEOUT_MS 100
54
55/*
56 * iATU Unroll-specific register definitions
57 * From 4.80 core version the address translation will be made by unroll.
58 * The registers are offset from atu_base
59 */
60#define PCIE_ATU_UNR_REGION_CTRL1 0x00
61#define PCIE_ATU_UNR_REGION_CTRL2 0x04
62#define PCIE_ATU_UNR_LOWER_BASE 0x08
63#define PCIE_ATU_UNR_UPPER_BASE 0x0c
64#define PCIE_ATU_UNR_LIMIT 0x10
65#define PCIE_ATU_UNR_LOWER_TARGET 0x14
66#define PCIE_ATU_UNR_UPPER_TARGET 0x18
67
68#define PCIE_ATU_REGION_INDEX1 (0x1 << 0)
69#define PCIE_ATU_REGION_INDEX0 (0x0 << 0)
70#define PCIE_ATU_TYPE_MEM (0x0 << 0)
71#define PCIE_ATU_TYPE_IO (0x2 << 0)
72#define PCIE_ATU_TYPE_CFG0 (0x4 << 0)
73#define PCIE_ATU_TYPE_CFG1 (0x5 << 0)
74#define PCIE_ATU_ENABLE (0x1 << 31)
75#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30)
76#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24)
77#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19)
78#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
79
80/* Register address builder */
81#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) ((region) << 9)
82
83/* Offsets from App base */
84#define PCIE_CMD_STATUS 0x04
85#define LTSSM_EN_VAL BIT(0)
86
87/* Parameters for the waiting for iATU enabled routine */
88#define LINK_WAIT_MAX_IATU_RETRIES 5
89#define LINK_WAIT_IATU 10000
90
91#define AM654_PCIE_DEV_TYPE_MASK 0x3
92#define EP 0x0
93#define LEG_EP 0x1
94#define RC 0x2
95
96/**
97 * struct pcie_dw_ti - TI DW PCIe controller state
98 *
99 * @app_base: The base address of application register space
100 * @dbics_base: The base address of dbics register space
101 * @cfg_base: The base address of configuration space
102 * @atu_base: The base address of ATU space
103 * @cfg_size: The size of the configuration space which is needed
104 * as it gets written into the PCIE_ATU_LIMIT register
105 * @first_busno: This driver supports multiple PCIe controllers.
106 * first_busno stores the bus number of the PCIe root-port
107 * number which may vary depending on the PCIe setup
108 * (PEX switches etc).
109 */
110struct pcie_dw_ti {
111 void *app_base;
112 void *dbi_base;
113 void *cfg_base;
114 void *atu_base;
115 fdt_size_t cfg_size;
116 int first_busno;
117 struct udevice *dev;
118
119 /* IO and MEM PCI regions */
120 struct pci_region io;
121 struct pci_region mem;
122};
123
124enum dw_pcie_device_mode {
125 DW_PCIE_UNKNOWN_TYPE,
126 DW_PCIE_EP_TYPE,
127 DW_PCIE_LEG_EP_TYPE,
128 DW_PCIE_RC_TYPE,
129};
130
131static int pcie_dw_get_link_speed(struct pcie_dw_ti *pci)
132{
133 return (readl(pci->dbi_base + PCIE_LINK_STATUS_REG) &
134 PCIE_LINK_STATUS_SPEED_MASK) >> PCIE_LINK_STATUS_SPEED_OFF;
135}
136
137static int pcie_dw_get_link_width(struct pcie_dw_ti *pci)
138{
139 return (readl(pci->dbi_base + PCIE_LINK_STATUS_REG) &
140 PCIE_LINK_STATUS_WIDTH_MASK) >> PCIE_LINK_STATUS_WIDTH_OFF;
141}
142
143static void dw_pcie_writel_ob_unroll(struct pcie_dw_ti *pci, u32 index, u32 reg,
144 u32 val)
145{
146 u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
147 void __iomem *base = pci->atu_base;
148
149 writel(val, base + offset + reg);
150}
151
152static u32 dw_pcie_readl_ob_unroll(struct pcie_dw_ti *pci, u32 index, u32 reg)
153{
154 u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
155 void __iomem *base = pci->atu_base;
156
157 return readl(base + offset + reg);
158}
159
160/**
161 * pcie_dw_prog_outbound_atu_unroll() - Configure ATU for outbound accesses
162 *
163 * @pcie: Pointer to the PCI controller state
164 * @index: ATU region index
165 * @type: ATU accsess type
166 * @cpu_addr: the physical address for the translation entry
167 * @pci_addr: the pcie bus address for the translation entry
168 * @size: the size of the translation entry
169 */
170static void pcie_dw_prog_outbound_atu_unroll(struct pcie_dw_ti *pci, int index,
171 int type, u64 cpu_addr,
172 u64 pci_addr, u32 size)
173{
174 u32 retries, val;
175
176 debug("ATU programmed with: index: %d, type: %d, cpu addr: %8llx, pci addr: %8llx, size: %8x\n",
177 index, type, cpu_addr, pci_addr, size);
178
179 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
180 lower_32_bits(cpu_addr));
181 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
182 upper_32_bits(cpu_addr));
183 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LIMIT,
184 lower_32_bits(cpu_addr + size - 1));
185 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
186 lower_32_bits(pci_addr));
187 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
188 upper_32_bits(pci_addr));
189 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
190 type);
191 dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
192 PCIE_ATU_ENABLE);
193
194 /*
195 * Make sure ATU enable takes effect before any subsequent config
196 * and I/O accesses.
197 */
198 for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
199 val = dw_pcie_readl_ob_unroll(pci, index,
200 PCIE_ATU_UNR_REGION_CTRL2);
201 if (val & PCIE_ATU_ENABLE)
202 return;
203
204 udelay(LINK_WAIT_IATU);
205 }
206 dev_err(pci->dev, "outbound iATU is not being enabled\n");
207}
208
209/**
210 * set_cfg_address() - Configure the PCIe controller config space access
211 *
212 * @pcie: Pointer to the PCI controller state
213 * @d: PCI device to access
214 * @where: Offset in the configuration space
215 *
216 * Configures the PCIe controller to access the configuration space of
217 * a specific PCIe device and returns the address to use for this
218 * access.
219 *
220 * Return: Address that can be used to access the configation space
221 * of the requested device / offset
222 */
223static uintptr_t set_cfg_address(struct pcie_dw_ti *pcie,
224 pci_dev_t d, uint where)
225{
226 int bus = PCI_BUS(d) - pcie->first_busno;
227 uintptr_t va_address;
228 u32 atu_type;
229
230 /* Use dbi_base for own configuration read and write */
231 if (!bus) {
232 va_address = (uintptr_t)pcie->dbi_base;
233 goto out;
234 }
235
236 if (bus == 1)
237 /* For local bus, change TLP Type field to 4. */
238 atu_type = PCIE_ATU_TYPE_CFG0;
239 else
240 /* Otherwise, change TLP Type field to 5. */
241 atu_type = PCIE_ATU_TYPE_CFG1;
242
243 /*
244 * Not accessing root port configuration space?
245 * Region #0 is used for Outbound CFG space access.
246 * Direction = Outbound
247 * Region Index = 0
248 */
249 d = PCI_MASK_BUS(d);
250 d = PCI_ADD_BUS(bus, d);
251 pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
252 atu_type, (u64)pcie->cfg_base,
253 d << 8, pcie->cfg_size);
254
255 va_address = (uintptr_t)pcie->cfg_base;
256
257out:
258 va_address += where & ~0x3;
259
260 return va_address;
261}
262
263/**
264 * pcie_dw_addr_valid() - Check for valid bus address
265 *
266 * @d: The PCI device to access
267 * @first_busno: Bus number of the PCIe controller root complex
268 *
269 * Return 1 (true) if the PCI device can be accessed by this controller.
270 *
271 * Return: 1 on valid, 0 on invalid
272 */
273static int pcie_dw_addr_valid(pci_dev_t d, int first_busno)
274{
275 if ((PCI_BUS(d) == first_busno) && (PCI_DEV(d) > 0))
276 return 0;
277 if ((PCI_BUS(d) == first_busno + 1) && (PCI_DEV(d) > 0))
278 return 0;
279
280 return 1;
281}
282
283/**
284 * pcie_dw_ti_read_config() - Read from configuration space
285 *
286 * @bus: Pointer to the PCI bus
287 * @bdf: Identifies the PCIe device to access
288 * @offset: The offset into the device's configuration space
289 * @valuep: A pointer at which to store the read value
290 * @size: Indicates the size of access to perform
291 *
292 * Read a value of size @size from offset @offset within the configuration
293 * space of the device identified by the bus, device & function numbers in @bdf
294 * on the PCI bus @bus.
295 *
296 * Return: 0 on success
297 */
Simon Glass2a311e82020-01-27 08:49:37 -0700298static int pcie_dw_ti_read_config(const struct udevice *bus, pci_dev_t bdf,
Sekhar Nori18db23d2019-08-01 19:12:57 +0530299 uint offset, ulong *valuep,
300 enum pci_size_t size)
301{
302 struct pcie_dw_ti *pcie = dev_get_priv(bus);
303 uintptr_t va_address;
304 ulong value;
305
306 debug("PCIE CFG read: bdf=%2x:%2x:%2x ",
307 PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
308
309 if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) {
310 debug("- out of range\n");
311 *valuep = pci_get_ff(size);
312 return 0;
313 }
314
315 va_address = set_cfg_address(pcie, bdf, offset);
316
317 value = readl(va_address);
318
319 debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
320 *valuep = pci_conv_32_to_size(value, offset, size);
321
322 pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
323 PCIE_ATU_TYPE_IO, pcie->io.phys_start,
324 pcie->io.bus_start, pcie->io.size);
325
326 return 0;
327}
328
329/**
330 * pcie_dw_ti_write_config() - Write to configuration space
331 *
332 * @bus: Pointer to the PCI bus
333 * @bdf: Identifies the PCIe device to access
334 * @offset: The offset into the device's configuration space
335 * @value: The value to write
336 * @size: Indicates the size of access to perform
337 *
338 * Write the value @value of size @size from offset @offset within the
339 * configuration space of the device identified by the bus, device & function
340 * numbers in @bdf on the PCI bus @bus.
341 *
342 * Return: 0 on success
343 */
344static int pcie_dw_ti_write_config(struct udevice *bus, pci_dev_t bdf,
345 uint offset, ulong value,
346 enum pci_size_t size)
347{
348 struct pcie_dw_ti *pcie = dev_get_priv(bus);
349 uintptr_t va_address;
350 ulong old;
351
352 debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ",
353 PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
354 debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
355
356 if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) {
357 debug("- out of range\n");
358 return 0;
359 }
360
361 va_address = set_cfg_address(pcie, bdf, offset);
362
363 old = readl(va_address);
364 value = pci_conv_size_to_32(old, value, offset, size);
365 writel(value, va_address);
366
367 pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
368 PCIE_ATU_TYPE_IO, pcie->io.phys_start,
369 pcie->io.bus_start, pcie->io.size);
370
371 return 0;
372}
373
374static inline void dw_pcie_dbi_write_enable(struct pcie_dw_ti *pci, bool en)
375{
376 u32 val;
377
378 val = readl(pci->dbi_base + PCIE_MISC_CONTROL_1_OFF);
379 if (en)
380 val |= PCIE_DBI_RO_WR_EN;
381 else
382 val &= ~PCIE_DBI_RO_WR_EN;
383 writel(val, pci->dbi_base + PCIE_MISC_CONTROL_1_OFF);
384}
385
386/**
387 * pcie_dw_configure() - Configure link capabilities and speed
388 *
389 * @regs_base: A pointer to the PCIe controller registers
390 * @cap_speed: The capabilities and speed to configure
391 *
392 * Configure the link capabilities and speed in the PCIe root complex.
393 */
394static void pcie_dw_configure(struct pcie_dw_ti *pci, u32 cap_speed)
395{
396 u32 val;
397
398 dw_pcie_dbi_write_enable(pci, true);
399
400 val = readl(pci->dbi_base + PCIE_LINK_CAPABILITY);
401 val &= ~TARGET_LINK_SPEED_MASK;
402 val |= cap_speed;
403 writel(val, pci->dbi_base + PCIE_LINK_CAPABILITY);
404
405 val = readl(pci->dbi_base + PCIE_LINK_CTL_2);
406 val &= ~TARGET_LINK_SPEED_MASK;
407 val |= cap_speed;
408 writel(val, pci->dbi_base + PCIE_LINK_CTL_2);
409
410 dw_pcie_dbi_write_enable(pci, false);
411}
412
413/**
414 * is_link_up() - Return the link state
415 *
416 * @regs_base: A pointer to the PCIe DBICS registers
417 *
418 * Return: 1 (true) for active line and 0 (false) for no link
419 */
420static int is_link_up(struct pcie_dw_ti *pci)
421{
422 u32 val;
423
424 val = readl(pci->dbi_base + PCIE_PORT_DEBUG0);
425 val &= PORT_LOGIC_LTSSM_STATE_MASK;
426
427 return (val == PORT_LOGIC_LTSSM_STATE_L0);
428}
429
430/**
431 * wait_link_up() - Wait for the link to come up
432 *
433 * @regs_base: A pointer to the PCIe controller registers
434 *
435 * Return: 1 (true) for active line and 0 (false) for no link (timeout)
436 */
437static int wait_link_up(struct pcie_dw_ti *pci)
438{
439 unsigned long timeout;
440
441 timeout = get_timer(0) + PCIE_LINK_UP_TIMEOUT_MS;
442 while (!is_link_up(pci)) {
443 if (get_timer(0) > timeout)
444 return 0;
445 };
446
447 return 1;
448}
449
450static int pcie_dw_ti_pcie_link_up(struct pcie_dw_ti *pci, u32 cap_speed)
451{
452 u32 val;
453
454 if (is_link_up(pci)) {
455 printf("PCI Link already up before configuration!\n");
456 return 1;
457 }
458
459 /* DW pre link configurations */
460 pcie_dw_configure(pci, cap_speed);
461
462 /* Initiate link training */
463 val = readl(pci->app_base + PCIE_CMD_STATUS);
464 val |= LTSSM_EN_VAL;
465 writel(val, pci->app_base + PCIE_CMD_STATUS);
466
467 /* Check that link was established */
468 if (!wait_link_up(pci))
469 return 0;
470
471 /*
472 * Link can be established in Gen 1. still need to wait
473 * till MAC nagaotiation is completed
474 */
475 udelay(100);
476
477 return 1;
478}
479
480/**
481 * pcie_dw_setup_host() - Setup the PCIe controller for RC opertaion
482 *
483 * @pcie: Pointer to the PCI controller state
484 *
485 * Configure the host BARs of the PCIe controller root port so that
486 * PCI(e) devices may access the system memory.
487 */
488static void pcie_dw_setup_host(struct pcie_dw_ti *pci)
489{
490 u32 val;
491
492 /* setup RC BARs */
493 writel(PCI_BASE_ADDRESS_MEM_TYPE_64,
494 pci->dbi_base + PCI_BASE_ADDRESS_0);
495 writel(0x0, pci->dbi_base + PCI_BASE_ADDRESS_1);
496
497 /* setup interrupt pins */
498 dw_pcie_dbi_write_enable(pci, true);
499 val = readl(pci->dbi_base + PCI_INTERRUPT_LINE);
500 val &= 0xffff00ff;
501 val |= 0x00000100;
502 writel(val, pci->dbi_base + PCI_INTERRUPT_LINE);
503 dw_pcie_dbi_write_enable(pci, false);
504
505 /* setup bus numbers */
506 val = readl(pci->dbi_base + PCI_PRIMARY_BUS);
507 val &= 0xff000000;
508 val |= 0x00ff0100;
509 writel(val, pci->dbi_base + PCI_PRIMARY_BUS);
510
511 /* setup command register */
512 val = readl(pci->dbi_base + PCI_COMMAND);
513 val &= 0xffff0000;
514 val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
515 PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
516 writel(val, pci->dbi_base + PCI_COMMAND);
517
518 /* Enable write permission for the DBI read-only register */
519 dw_pcie_dbi_write_enable(pci, true);
520 /* program correct class for RC */
521 writew(PCI_CLASS_BRIDGE_PCI, pci->dbi_base + PCI_CLASS_DEVICE);
522 /* Better disable write permission right after the update */
523 dw_pcie_dbi_write_enable(pci, false);
524
525 val = readl(pci->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
526 val |= PORT_LOGIC_SPEED_CHANGE;
527 writel(val, pci->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
528}
529
530static int pcie_am654_set_mode(struct pcie_dw_ti *pci,
531 enum dw_pcie_device_mode mode)
532{
533 struct regmap *syscon;
534 u32 val;
535 u32 mask;
536 int ret;
537
538 syscon = syscon_regmap_lookup_by_phandle(pci->dev,
539 "ti,syscon-pcie-mode");
540 if (IS_ERR(syscon))
541 return 0;
542
543 mask = AM654_PCIE_DEV_TYPE_MASK;
544
545 switch (mode) {
546 case DW_PCIE_RC_TYPE:
547 val = RC;
548 break;
549 case DW_PCIE_EP_TYPE:
550 val = EP;
551 break;
552 default:
553 dev_err(pci->dev, "INVALID device type %d\n", mode);
554 return -EINVAL;
555 }
556
557 ret = regmap_update_bits(syscon, 0, mask, val);
558 if (ret) {
559 dev_err(pci->dev, "failed to set pcie mode\n");
560 return ret;
561 }
562
563 return 0;
564}
565
566static int pcie_dw_init_id(struct pcie_dw_ti *pci)
567{
568 struct regmap *devctrl_regs;
569 unsigned int id;
570 int ret;
571
572 devctrl_regs = syscon_regmap_lookup_by_phandle(pci->dev,
573 "ti,syscon-pcie-id");
574 if (IS_ERR(devctrl_regs))
575 return PTR_ERR(devctrl_regs);
576
577 ret = regmap_read(devctrl_regs, 0, &id);
578 if (ret)
579 return ret;
580
581 dw_pcie_dbi_write_enable(pci, true);
582 writew(id & PCIE_VENDORID_MASK, pci->dbi_base + PCI_VENDOR_ID);
583 writew(id >> PCIE_DEVICEID_SHIFT, pci->dbi_base + PCI_DEVICE_ID);
584 dw_pcie_dbi_write_enable(pci, false);
585
586 return 0;
587}
588
589/**
590 * pcie_dw_ti_probe() - Probe the PCIe bus for active link
591 *
592 * @dev: A pointer to the device being operated on
593 *
594 * Probe for an active link on the PCIe bus and configure the controller
595 * to enable this port.
596 *
597 * Return: 0 on success, else -ENODEV
598 */
599static int pcie_dw_ti_probe(struct udevice *dev)
600{
601 struct pcie_dw_ti *pci = dev_get_priv(dev);
602 struct udevice *ctlr = pci_get_controller(dev);
603 struct pci_controller *hose = dev_get_uclass_priv(ctlr);
604 struct power_domain pci_pwrdmn;
605 struct phy phy0, phy1;
606 int ret;
607
608 ret = power_domain_get_by_index(dev, &pci_pwrdmn, 0);
609 if (ret) {
610 dev_err(dev, "failed to get power domain\n");
611 return ret;
612 }
613
614 ret = power_domain_on(&pci_pwrdmn);
615 if (ret) {
616 dev_err(dev, "Power domain on failed\n");
617 return ret;
618 }
619
620 ret = generic_phy_get_by_name(dev, "pcie-phy0", &phy0);
621 if (ret) {
622 dev_err(dev, "Unable to get phy0");
623 return ret;
624 }
625 generic_phy_reset(&phy0);
626 generic_phy_init(&phy0);
627 generic_phy_power_on(&phy0);
628
629 ret = generic_phy_get_by_name(dev, "pcie-phy1", &phy1);
630 if (ret) {
631 dev_err(dev, "Unable to get phy1");
632 return ret;
633 }
634 generic_phy_reset(&phy1);
635 generic_phy_init(&phy1);
636 generic_phy_power_on(&phy1);
637
Simon Glass75e534b2020-12-16 21:20:07 -0700638 pci->first_busno = dev_seq(dev);
Sekhar Nori18db23d2019-08-01 19:12:57 +0530639 pci->dev = dev;
640
641 pcie_dw_setup_host(pci);
642 pcie_dw_init_id(pci);
643
644 if (device_is_compatible(dev, "ti,am654-pcie-rc"))
645 pcie_am654_set_mode(pci, DW_PCIE_RC_TYPE);
646
647 if (!pcie_dw_ti_pcie_link_up(pci, LINK_SPEED_GEN_2)) {
Simon Glass75e534b2020-12-16 21:20:07 -0700648 printf("PCIE-%d: Link down\n", dev_seq(dev));
Sekhar Nori18db23d2019-08-01 19:12:57 +0530649 return -ENODEV;
650 }
651
Simon Glass75e534b2020-12-16 21:20:07 -0700652 printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n", dev_seq(dev),
Sekhar Nori18db23d2019-08-01 19:12:57 +0530653 pcie_dw_get_link_speed(pci),
654 pcie_dw_get_link_width(pci),
655 hose->first_busno);
656
657 /* Store the IO and MEM windows settings for future use by the ATU */
658 pci->io.phys_start = hose->regions[0].phys_start; /* IO base */
659 pci->io.bus_start = hose->regions[0].bus_start; /* IO_bus_addr */
660 pci->io.size = hose->regions[0].size; /* IO size */
661
662 pci->mem.phys_start = hose->regions[1].phys_start; /* MEM base */
663 pci->mem.bus_start = hose->regions[1].bus_start; /* MEM_bus_addr */
664 pci->mem.size = hose->regions[1].size; /* MEM size */
665
666 pcie_dw_prog_outbound_atu_unroll(pci, PCIE_ATU_REGION_INDEX0,
667 PCIE_ATU_TYPE_MEM,
668 pci->mem.phys_start,
669 pci->mem.bus_start, pci->mem.size);
670
671 return 0;
672}
673
674/**
Simon Glassaad29ae2020-12-03 16:55:21 -0700675 * pcie_dw_ti_of_to_plat() - Translate from DT to device state
Sekhar Nori18db23d2019-08-01 19:12:57 +0530676 *
677 * @dev: A pointer to the device being operated on
678 *
679 * Translate relevant data from the device tree pertaining to device @dev into
680 * state that the driver will later make use of. This state is stored in the
681 * device's private data structure.
682 *
683 * Return: 0 on success, else -EINVAL
684 */
Simon Glassaad29ae2020-12-03 16:55:21 -0700685static int pcie_dw_ti_of_to_plat(struct udevice *dev)
Sekhar Nori18db23d2019-08-01 19:12:57 +0530686{
687 struct pcie_dw_ti *pcie = dev_get_priv(dev);
688
689 /* Get the controller base address */
690 pcie->dbi_base = (void *)dev_read_addr_name(dev, "dbics");
691 if ((fdt_addr_t)pcie->dbi_base == FDT_ADDR_T_NONE)
692 return -EINVAL;
693
694 /* Get the config space base address and size */
695 pcie->cfg_base = (void *)dev_read_addr_size_name(dev, "config",
696 &pcie->cfg_size);
697 if ((fdt_addr_t)pcie->cfg_base == FDT_ADDR_T_NONE)
698 return -EINVAL;
699
700 /* Get the iATU base address and size */
701 pcie->atu_base = (void *)dev_read_addr_name(dev, "atu");
702 if ((fdt_addr_t)pcie->atu_base == FDT_ADDR_T_NONE)
703 return -EINVAL;
704
705 /* Get the app base address and size */
706 pcie->app_base = (void *)dev_read_addr_name(dev, "app");
707 if ((fdt_addr_t)pcie->app_base == FDT_ADDR_T_NONE)
708 return -EINVAL;
709
710 return 0;
711}
712
713static const struct dm_pci_ops pcie_dw_ti_ops = {
714 .read_config = pcie_dw_ti_read_config,
715 .write_config = pcie_dw_ti_write_config,
716};
717
718static const struct udevice_id pcie_dw_ti_ids[] = {
719 { .compatible = "ti,am654-pcie-rc" },
720 { }
721};
722
723U_BOOT_DRIVER(pcie_dw_ti) = {
724 .name = "pcie_dw_ti",
725 .id = UCLASS_PCI,
726 .of_match = pcie_dw_ti_ids,
727 .ops = &pcie_dw_ti_ops,
Simon Glassaad29ae2020-12-03 16:55:21 -0700728 .of_to_plat = pcie_dw_ti_of_to_plat,
Sekhar Nori18db23d2019-08-01 19:12:57 +0530729 .probe = pcie_dw_ti_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700730 .priv_auto = sizeof(struct pcie_dw_ti),
Sekhar Nori18db23d2019-08-01 19:12:57 +0530731};