blob: fc855dfca4eb23022b4805883eb6d9f812aa6a6f [file] [log] [blame]
Masami Hiramatsu06850202021-06-04 18:44:06 +09001// SPDX-License-Identifier: GPL-2.0
2/*
3 * SynQuacer PCIE host driver
4 *
5 * Based on drivers/pci/pcie_ecam_generic.c
6 *
7 * Copyright (C) 2016 Imagination Technologies
8 * Copyright (C) 2021 Linaro Ltd.
9 */
10
Masami Hiramatsu06850202021-06-04 18:44:06 +090011#include <dm.h>
12#include <pci.h>
13#include <log.h>
14
15#include <asm/io.h>
16#include <linux/bitops.h>
17#include <linux/delay.h>
18
19/* iATU registers */
20#define IATU_VIEWPORT_OFF 0x900
21#define IATU_VIEWPORT_INBOUND BIT(31)
22#define IATU_VIEWPORT_OUTBOUND 0
23#define IATU_VIEWPORT_REGION_INDEX(idx) ((idx) & 7)
24
25#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0 0x904
26#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM 0x0
27#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO 0x2
28#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0 0x4
29#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1 0x5
30#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TH BIT(12)
31
32#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0 0x908
33#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN BIT(31)
34#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE BIT(28)
35#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_MSG_CODE_32BIT 0xF
36#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_MSG_CODE_64BIT 0xFF
37
38#define IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0 0x90C
39#define IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0 0x910
40#define IATU_LIMIT_ADDR_OFF_OUTBOUND_0 0x914
41#define IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0 0x918
42#define IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0 0x91C
43
44/* Clock and resets */
45#define CORE_CONTROL 0x000
46#define APP_LTSSM_ENABLE BIT(4)
47#define DEVICE_TYPE (BIT(3) | BIT(2) | BIT(1) | BIT(0))
48
49#define AXI_CLK_STOP 0x004
50#define DBI_ACLK_STOP BIT(8)
51#define SLV_ACLK_STOP BIT(4)
52#define MSTR_ACLK_STOP BIT(0)
53#define DBI_CSYSREQ_REG BIT(9)
54#define SLV_CSYSREQ_REG BIT(5)
55#define MSTR_CSYSREQ_REG BIT(1)
56
57#define RESET_CONTROL_1 0x00C
58#define PERST_N_O_REG BIT(5)
59#define PERST_N_I_REG BIT(4)
60#define BUTTON_RST_N_REG BIT(1)
61#define PWUP_RST_N_REG BIT(0)
62
63#define RESET_CONTROL_2 0x010
64
65#define RESET_SELECT_1 0x014
66#define SQU_RST_SEL BIT(29)
67#define PHY_RST_SEL BIT(28)
68#define PWR_RST_SEL BIT(24)
69#define STI_RST_SEL BIT(20)
70#define N_STI_RST_SEL BIT(16)
71#define CORE_RST_SEL BIT(12)
72#define PERST_SEL BIT(4)
73#define BUTTON_RST_SEL BIT(1)
74#define PWUP_RST_SEL BIT(0)
75
76#define RESET_SELECT_2 0x018
77#define DBI_ARST_SEL BIT(8)
78#define SLV_ARST_SEL BIT(4)
79#define MSTR_ARST_SEL BIT(0)
80
81#define EM_CONTROL 0x030
82#define PRE_DET_STT_REG BIT(4)
83
84#define EM_SELECT 0x034
85#define PRE_DET_STT_SEL BIT(4)
86
87#define PM_CONTROL_2 0x050
88#define SYS_AUX_PWR_DET BIT(8)
89
90#define PHY_CONFIG_COM_6 0x114
91#define PIPE_PORT_SEL GENMASK(1, 0)
92
93#define LINK_MONITOR 0x210
94#define SMLH_LINK_UP BIT(0)
95
96#define LINK_CAPABILITIES_REG 0x07C
97#define PCIE_CAP_MAX_LINK_WIDTH GENMASK(7, 4)
98#define PCIE_CAP_MAX_LINK_SPEED GENMASK(3, 0)
99
100#define LINK_CONTROL_LINK_STATUS_REG 0x080
101#define PCIE_CAP_NEGO_LINK_WIDTH GENMASK(23, 20)
102#define PCIE_CAP_LINK_SPEED GENMASK(19, 16)
103
104#define TYPE1_CLASS_CODE_REV_ID_REG 0x008
105#define BASE_CLASS_CODE 0xFF000000
106#define BASE_CLASS_CODE_VALUE 0x06
107#define SUBCLASS_CODE 0x00FF0000
108#define SUBCLASS_CODE_VALUE 0x04
109#define PROGRAM_INTERFACE 0x0000FF00
110#define PROGRAM_INTERFACE_VALUE 0x00
111
112#define GEN2_CONTROL_OFF 0x80c
113#define DIRECT_SPEED_CHANGE BIT(17)
114
115#define MISC_CONTROL_1_OFF 0x8BC
116#define DBI_RO_WR_EN BIT(0)
117
118static void or_writel(void *base, u32 offs, u32 val)
119{
120 writel(readl(base + offs) | val, base + offs);
121}
122
123static void masked_writel(void *base, u32 offs, u32 mask, u32 val)
124{
125 u32 data;
126 int shift = ffs(mask); /* Note that ffs() returns 1 for 0x1 */
127
128 if (val && shift > 1)
129 val <<= shift - 1;
130
131 if (mask != ~0)
132 data = (readl(base + offs) & ~mask) | val;
133 else
134 data = val;
135
136 writel(data, base + offs);
137}
138
139static u32 masked_readl(void *base, u32 offs, u32 mask)
140{
141 u32 data;
142 int shift = ffs(mask); /* Note that ffs() returns 1 for 0x1 */
143
144 data = readl(base + offs);
145
146 if (mask != ~0)
147 data &= mask;
148 if (shift > 1)
149 data >>= shift - 1;
150
151 return data;
152}
153
154/*
155 * Since SynQuacer's PCIe RC is expected to be initialized in the
156 * firmware (including U-Boot), devicetree doesn't have control
157 * blocks.
158 *
159 * Thus, this will initialize the PCIe RC with fixed addresses.
160 */
161
162#define SYNQUACER_PCI_SEG0_CONFIG_BASE 0x60000000
163#define SYNQUACER_PCI_SEG0_CONFIG_SIZE 0x07f00000
164#define SYNQUACER_PCI_SEG0_DBI_BASE 0x583d0000
165#define SYNQUACER_PCI_SEG0_EXS_BASE 0x58390000
166
167#define SYNQUACER_PCI_SEG1_CONFIG_BASE 0x70000000
168#define SYNQUACER_PCI_SEG1_CONFIG_SIZE 0x07f00000
169#define SYNQUACER_PCI_SEG1_DBI_BASE 0x583c0000
170#define SYNQUACER_PCI_SEG1_EXS_BASE 0x58380000
171
172#define SIZE_16KB 0x00004000
173#define SIZE_64KB 0x00010000
174#define SIZE_1MB 0x00100000
175
176#define SYNQUACER_PCI_DBI_SIZE SIZE_16KB
177#define SYNQUACER_PCI_EXS_SIZE SIZE_64KB
178
179#define NUM_SQ_PCI_RC 2
180
181static const struct synquacer_pcie_base {
182 phys_addr_t cfg_base;
183 phys_addr_t dbi_base;
184 phys_addr_t exs_base;
185} synquacer_pci_bases[NUM_SQ_PCI_RC] = {
186 {
187 .cfg_base = SYNQUACER_PCI_SEG0_CONFIG_BASE,
188 .dbi_base = SYNQUACER_PCI_SEG0_DBI_BASE,
189 .exs_base = SYNQUACER_PCI_SEG0_EXS_BASE,
190 }, {
191 .cfg_base = SYNQUACER_PCI_SEG1_CONFIG_BASE,
192 .dbi_base = SYNQUACER_PCI_SEG1_DBI_BASE,
193 .exs_base = SYNQUACER_PCI_SEG1_EXS_BASE,
194 },
195};
196
197/**
198 * struct synquacer_ecam_pcie - synquacer_ecam PCIe controller state
199 * @cfg_base: The base address of memory mapped configuration space
200 */
201struct synquacer_ecam_pcie {
202 void *cfg_base;
203 pci_size_t size;
204 void *dbi_base;
205 void *exs_base;
206 int first_busno;
207
208 struct pci_region mem;
209 struct pci_region io;
210 struct pci_region mem64;
211};
212
213DECLARE_GLOBAL_DATA_PTR;
214
215/**
216 * pci_synquacer_ecam_conf_address() - Calculate the address of a config access
217 * @bus: Pointer to the PCI bus
218 * @bdf: Identifies the PCIe device to access
219 * @offset: The offset into the device's configuration space
220 * @paddress: Pointer to the pointer to write the calculates address to
221 *
222 * Calculates the address that should be accessed to perform a PCIe
223 * configuration space access for a given device identified by the PCIe
224 * controller device @pcie and the bus, device & function numbers in @bdf. If
225 * access to the device is not valid then the function will return an error
226 * code. Otherwise the address to access will be written to the pointer pointed
227 * to by @paddress.
228 */
229static int pci_synquacer_ecam_conf_address(const struct udevice *bus,
230 pci_dev_t bdf, uint offset,
231 void **paddress)
232{
233 struct synquacer_ecam_pcie *pcie = dev_get_priv(bus);
234 void *addr;
235
236 addr = pcie->cfg_base;
Pali Rohár23769352021-11-03 01:01:05 +0100237 addr += PCIE_ECAM_OFFSET(PCI_BUS(bdf) - pcie->first_busno,
238 PCI_DEV(bdf), PCI_FUNC(bdf), offset);
Masami Hiramatsu06850202021-06-04 18:44:06 +0900239 *paddress = addr;
240
241 return 0;
242}
243
244static bool pci_synquacer_ecam_addr_valid(const struct udevice *bus,
245 pci_dev_t bdf)
246{
247 struct synquacer_ecam_pcie *pcie = dev_get_priv(bus);
248 int num_buses = DIV_ROUND_UP(pcie->size, 1 << 16);
249
250 /*
251 * The Synopsys DesignWare PCIe controller in ECAM mode will not filter
252 * type 0 config TLPs sent to devices 1 and up on its downstream port,
253 * resulting in devices appearing multiple times on bus 0 unless we
254 * filter out those accesses here.
255 */
256 if (PCI_BUS(bdf) == pcie->first_busno && PCI_DEV(bdf) > 0)
257 return false;
258
259 return (PCI_BUS(bdf) >= pcie->first_busno &&
260 PCI_BUS(bdf) < pcie->first_busno + num_buses);
261}
262
263/**
264 * pci_synquacer_ecam_read_config() - Read from configuration space
265 * @bus: Pointer to the PCI bus
266 * @bdf: Identifies the PCIe device to access
267 * @offset: The offset into the device's configuration space
268 * @valuep: A pointer at which to store the read value
269 * @size: Indicates the size of access to perform
270 *
271 * Read a value of size @size from offset @offset within the configuration
272 * space of the device identified by the bus, device & function numbers in @bdf
273 * on the PCI bus @bus.
274 */
275static int pci_synquacer_ecam_read_config(const struct udevice *bus,
276 pci_dev_t bdf, uint offset,
277 ulong *valuep, enum pci_size_t size)
278{
279 if (!pci_synquacer_ecam_addr_valid(bus, bdf)) {
280 *valuep = pci_get_ff(size);
281 return 0;
282 }
283
284 return pci_generic_mmap_read_config(bus, pci_synquacer_ecam_conf_address,
285 bdf, offset, valuep, size);
286}
287
288/**
289 * pci_synquacer_ecam_write_config() - Write to configuration space
290 * @bus: Pointer to the PCI bus
291 * @bdf: Identifies the PCIe device to access
292 * @offset: The offset into the device's configuration space
293 * @value: The value to write
294 * @size: Indicates the size of access to perform
295 *
296 * Write the value @value of size @size from offset @offset within the
297 * configuration space of the device identified by the bus, device & function
298 * numbers in @bdf on the PCI bus @bus.
299 */
300static int pci_synquacer_ecam_write_config(struct udevice *bus, pci_dev_t bdf,
301 uint offset, ulong value,
302 enum pci_size_t size)
303{
304 if (!pci_synquacer_ecam_addr_valid(bus, bdf))
305 return 0;
306
307 return pci_generic_mmap_write_config(bus, pci_synquacer_ecam_conf_address,
308 bdf, offset, value, size);
309}
310
311/**
312 * pci_synquacer_ecam_of_to_plat() - Translate from DT to device state
313 * @dev: A pointer to the device being operated on
314 *
315 * Translate relevant data from the device tree pertaining to device @dev into
316 * state that the driver will later make use of. This state is stored in the
317 * device's private data structure.
318 *
319 * Return: 0 on success, else -EINVAL
320 */
321static int pci_synquacer_ecam_of_to_plat(struct udevice *dev)
322{
323 struct synquacer_ecam_pcie *pcie = dev_get_priv(dev);
324 struct fdt_resource reg_res;
325 int i, err;
326
327 debug("%s: called for %s\n", __func__, dev->name);
328
329 err = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev), "reg",
330 0, &reg_res);
331 if (err < 0) {
332 pr_err("\"reg\" resource not found\n");
333 return err;
334 }
335
336 /* Find the correct pair of the DBI/EXS base address */
337 for (i = 0; i < NUM_SQ_PCI_RC; i++) {
338 if (synquacer_pci_bases[i].cfg_base == reg_res.start)
339 break;
340 }
341 if (i == NUM_SQ_PCI_RC) {
342 pr_err("Unknown ECAM base address %lx.\n",
343 (unsigned long)reg_res.start);
344 return -ENOENT;
345 }
346 pcie->dbi_base = map_physmem(synquacer_pci_bases[i].dbi_base,
347 SYNQUACER_PCI_DBI_SIZE, MAP_NOCACHE);
348 if (!pcie->dbi_base) {
349 pr_err("Failed to map DBI for %s\n", dev->name);
350 return -ENOMEM;
351 }
352
353 pcie->exs_base = map_physmem(synquacer_pci_bases[i].exs_base,
354 SYNQUACER_PCI_EXS_SIZE, MAP_NOCACHE);
355 if (!pcie->exs_base) {
356 pr_err("Failed to map EXS for %s\n", dev->name);
357 return -ENOMEM;
358 }
359
360 pcie->size = fdt_resource_size(&reg_res);
361 pcie->cfg_base = map_physmem(reg_res.start, pcie->size, MAP_NOCACHE);
362 if (!pcie->cfg_base) {
363 pr_err("Failed to map config space for %s\n", dev->name);
364 return -ENOMEM;
365 }
366 debug("mappings DBI: %p EXS: %p CFG: %p\n", pcie->dbi_base, pcie->exs_base, pcie->cfg_base);
367
368 return 0;
369}
370
371static void pci_synquacer_pre_init(struct synquacer_ecam_pcie *pcie)
372{
373 void *base = pcie->exs_base;
374
375 masked_writel(base, EM_SELECT, PRE_DET_STT_SEL, 0);
376 masked_writel(base, EM_CONTROL, PRE_DET_STT_REG, 0);
377 masked_writel(base, EM_CONTROL, PRE_DET_STT_REG, 1);
378
379 /* 1: Assert all PHY / LINK resets */
380 masked_writel(base, RESET_SELECT_1, PERST_SEL, 0);
381 masked_writel(base, RESET_CONTROL_1, PERST_N_I_REG, 0);
382 masked_writel(base, RESET_CONTROL_1, PERST_N_O_REG, 0);
383
384 /* Device Reset(PERST#) is effective afrer Set device_type (RC) */
385 masked_writel(base, RESET_SELECT_1, PWUP_RST_SEL, 0);
386 masked_writel(base, RESET_CONTROL_1, PWUP_RST_N_REG, 0);
387 masked_writel(base, RESET_SELECT_1, BUTTON_RST_SEL, 0);
388 masked_writel(base, RESET_CONTROL_1, BUTTON_RST_N_REG, 0);
389 masked_writel(base, RESET_SELECT_1, PWR_RST_SEL, 1);
390 masked_writel(base, RESET_SELECT_2, MSTR_ARST_SEL, 1);
391 masked_writel(base, RESET_SELECT_2, SLV_ARST_SEL, 1);
392 masked_writel(base, RESET_SELECT_2, DBI_ARST_SEL, 1);
393 masked_writel(base, RESET_SELECT_1, CORE_RST_SEL, 1);
394 masked_writel(base, RESET_SELECT_1, STI_RST_SEL, 1);
395 masked_writel(base, RESET_SELECT_1, N_STI_RST_SEL, 1);
396 masked_writel(base, RESET_SELECT_1, SQU_RST_SEL, 1);
397 masked_writel(base, RESET_SELECT_1, PHY_RST_SEL, 1);
398
399 /* 2: Set P<n>_app_ltssm_enable='0' for reprogramming before linkup. */
400 masked_writel(base, CORE_CONTROL, APP_LTSSM_ENABLE, 0);
401
402 /* 3: Set device_type (RC) */
403 masked_writel(base, CORE_CONTROL, DEVICE_TYPE, 4);
404}
405
406static void pci_synquacer_dbi_init(void *dbi_base)
407{
408 masked_writel(dbi_base, MISC_CONTROL_1_OFF, DBI_RO_WR_EN, 1);
409 /* 4 Lanes */
410 masked_writel(dbi_base, LINK_CAPABILITIES_REG,
411 PCIE_CAP_MAX_LINK_WIDTH, 4);
412 /* Gen 2 */
413 masked_writel(dbi_base, LINK_CAPABILITIES_REG,
414 PCIE_CAP_MAX_LINK_SPEED, 2);
415
416 masked_writel(dbi_base, TYPE1_CLASS_CODE_REV_ID_REG,
417 BASE_CLASS_CODE, BASE_CLASS_CODE_VALUE);
418 masked_writel(dbi_base, TYPE1_CLASS_CODE_REV_ID_REG,
419 SUBCLASS_CODE, SUBCLASS_CODE_VALUE);
420 masked_writel(dbi_base, TYPE1_CLASS_CODE_REV_ID_REG,
421 PROGRAM_INTERFACE, PROGRAM_INTERFACE_VALUE);
422
423 masked_writel(dbi_base, MISC_CONTROL_1_OFF, DBI_RO_WR_EN, 0);
424}
425
426static void pcie_sq_prog_outbound_atu(void *dbi_base, int index,
427 u64 cpu_base, u64 pci_base, u64 size,
428 u32 type, u32 flags)
429{
430 debug("%s: %p, %d, %llx, %llx, %llx, %x, %x\n", __func__,
431 dbi_base, index, cpu_base, pci_base, size, type, flags);
432
433 writel(IATU_VIEWPORT_OUTBOUND | IATU_VIEWPORT_REGION_INDEX(index),
434 dbi_base + IATU_VIEWPORT_OFF);
435
436 writel((u32)(cpu_base & 0xffffffff),
437 dbi_base + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0);
438 writel((u32)(cpu_base >> 32),
439 dbi_base + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0);
440 writel((u32)(cpu_base + size - 1),
441 dbi_base + IATU_LIMIT_ADDR_OFF_OUTBOUND_0);
442
443 writel((u32)(pci_base & 0xffffffff),
444 dbi_base + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0);
445 writel((u32)(pci_base >> 32),
446 dbi_base + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0);
447
448 writel(type, dbi_base + IATU_REGION_CTRL_1_OFF_OUTBOUND_0);
449 writel(IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN | flags,
450 dbi_base + IATU_REGION_CTRL_2_OFF_OUTBOUND_0);
451}
452
453static void pci_synquacer_post_init(struct synquacer_ecam_pcie *pcie)
454{
455 void *base = pcie->exs_base;
456
457 /*
458 * 4: Set Bifurcation 1=disable 4=able
459 * 5: Supply Reference (It has executed)
460 * 6: Wait for 10usec (Reference Clocks is stable)
461 * 7: De assert PERST#
462 */
463 masked_writel(base, RESET_CONTROL_1, PERST_N_I_REG, 1);
464 masked_writel(base, RESET_CONTROL_1, PERST_N_O_REG, 1);
465
466 /* 8: Assert SYS_AUX_PWR_DET */
467 masked_writel(base, PM_CONTROL_2, SYS_AUX_PWR_DET, 1);
468
469 /* 9: Supply following clocks */
470 masked_writel(base, AXI_CLK_STOP, MSTR_CSYSREQ_REG, 1);
471 masked_writel(base, AXI_CLK_STOP, MSTR_ACLK_STOP, 0);
472 masked_writel(base, AXI_CLK_STOP, SLV_CSYSREQ_REG, 1);
473 masked_writel(base, AXI_CLK_STOP, SLV_ACLK_STOP, 0);
474 masked_writel(base, AXI_CLK_STOP, DBI_CSYSREQ_REG, 1);
475 masked_writel(base, AXI_CLK_STOP, DBI_ACLK_STOP, 0);
476
477 /*
478 * 10: De assert PHY reset
479 * 11: De assert LINK's PMC reset
480 */
481 masked_writel(base, RESET_CONTROL_1, PWUP_RST_N_REG, 1);
482 masked_writel(base, RESET_CONTROL_1, BUTTON_RST_N_REG, 1);
483
484 /* 12: PHY auto
485 * 13: Wrapper auto
486 * 14-17: PHY auto
487 * 18: Wrapper auto
488 * 19: Update registers through DBI AXI Slave interface
489 */
490 pci_synquacer_dbi_init(pcie->dbi_base);
491
492 or_writel(pcie->dbi_base, PCI_COMMAND,
493 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
494
495 /* Force link speed change to Gen2 at link up */
496 or_writel(pcie->dbi_base, GEN2_CONTROL_OFF, DIRECT_SPEED_CHANGE);
497
498 /* Region 0: MMIO32 range */
499 pcie_sq_prog_outbound_atu(pcie->dbi_base, 0,
500 pcie->mem.phys_start,
501 pcie->mem.bus_start,
502 pcie->mem.size,
503 IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM |
504 IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TH,
505 IATU_REGION_CTRL_2_OFF_OUTBOUND_0_MSG_CODE_32BIT);
506
507 /* Region 1: Type 0 config space */
508 pcie_sq_prog_outbound_atu(pcie->dbi_base, 1,
509 (u64)pcie->cfg_base,
510 0,
511 SIZE_64KB,
512 IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0,
513 IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE);
514
515 /* Region 2: Type 1 config space */
516 pcie_sq_prog_outbound_atu(pcie->dbi_base, 2,
517 (u64)pcie->cfg_base + SIZE_64KB,
518 0,
519 (u64)pcie->io.phys_start - (u64)pcie->cfg_base - SIZE_64KB,
520 IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1,
521 IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE);
522
523 /* Region 3: port I/O range */
524 pcie_sq_prog_outbound_atu(pcie->dbi_base, 3,
525 pcie->io.phys_start,
526 pcie->io.bus_start,
527 pcie->io.size,
528 IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO,
529 0);
530
531 /* Region 4: MMIO64 range */
532 pcie_sq_prog_outbound_atu(pcie->dbi_base, 4,
533 pcie->mem64.phys_start,
534 pcie->mem64.bus_start,
535 pcie->mem64.size,
536 IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM |
537 IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TH,
538 IATU_REGION_CTRL_2_OFF_OUTBOUND_0_MSG_CODE_32BIT);
539
540 /* enable link */
541 if (masked_readl(base, CORE_CONTROL, APP_LTSSM_ENABLE) == 0)
542 masked_writel(base, CORE_CONTROL, APP_LTSSM_ENABLE, 1);
543}
544
545static int pci_synquacer_ecam_probe(struct udevice *dev)
546{
547 struct synquacer_ecam_pcie *pcie = dev_get_priv(dev);
548 struct udevice *ctlr = pci_get_controller(dev);
549 struct pci_controller *hose = dev_get_uclass_priv(ctlr);
550
551 debug("Probe synquacer pcie for bus %d\n", dev_seq(dev));
552 pcie->first_busno = dev_seq(dev);
553
554 /* Store the IO and MEM windows settings for configuring ATU */
555 pcie->io.phys_start = hose->regions[0].phys_start; /* IO base */
556 pcie->io.bus_start = hose->regions[0].bus_start; /* IO_bus_addr */
557 pcie->io.size = hose->regions[0].size; /* IO size */
558
559 pcie->mem.phys_start = hose->regions[1].phys_start; /* MEM base */
560 pcie->mem.bus_start = hose->regions[1].bus_start; /* MEM_bus_addr */
561 pcie->mem.size = hose->regions[1].size; /* MEM size */
562
563 pcie->mem64.phys_start = hose->regions[2].phys_start; /* MEM64 base */
564 pcie->mem64.bus_start = hose->regions[2].bus_start; /* MEM64_bus_addr */
565 pcie->mem64.size = hose->regions[2].size; /* MEM64 size */
566
567 pci_synquacer_pre_init(pcie);
568
569 mdelay(150);
570
571 pci_synquacer_post_init(pcie);
572
573 /* It takes a while to stabilize the PCIe bus for scanning */
574 mdelay(100);
575
576 return 0;
577}
578
579static const struct dm_pci_ops pci_synquacer_ecam_ops = {
580 .read_config = pci_synquacer_ecam_read_config,
581 .write_config = pci_synquacer_ecam_write_config,
582};
583
584static const struct udevice_id pci_synquacer_ecam_ids[] = {
585 { .compatible = "socionext,synquacer-pcie-ecam" },
586 { }
587};
588
589U_BOOT_DRIVER(pci_synquacer_ecam) = {
590 .name = "pci_synquacer_ecam",
591 .id = UCLASS_PCI,
592 .of_match = pci_synquacer_ecam_ids,
593 .ops = &pci_synquacer_ecam_ops,
594 .probe = pci_synquacer_ecam_probe,
595 .of_to_plat = pci_synquacer_ecam_of_to_plat,
596 .priv_auto = sizeof(struct synquacer_ecam_pcie),
597};