blob: c649ab4ab2c00a6440e9cbcf44e85576a01ce742 [file] [log] [blame]
Ryder Lee637cfaca2017-05-21 11:42:24 +08001/*
2 * MediaTek PCIe host controller driver.
3 *
4 * Copyright (c) 2017 MediaTek Inc.
5 * Author: Ryder Lee <ryder.lee@mediatek.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/clk.h>
18#include <linux/delay.h>
Ryder Leee10b7a12017-08-10 14:34:54 +080019#include <linux/iopoll.h>
Ryder Lee637cfaca2017-05-21 11:42:24 +080020#include <linux/kernel.h>
21#include <linux/of_address.h>
22#include <linux/of_pci.h>
23#include <linux/of_platform.h>
24#include <linux/pci.h>
25#include <linux/phy/phy.h>
26#include <linux/platform_device.h>
27#include <linux/pm_runtime.h>
28#include <linux/reset.h>
29
30/* PCIe shared registers */
31#define PCIE_SYS_CFG 0x00
32#define PCIE_INT_ENABLE 0x0c
33#define PCIE_CFG_ADDR 0x20
34#define PCIE_CFG_DATA 0x24
35
36/* PCIe per port registers */
37#define PCIE_BAR0_SETUP 0x10
38#define PCIE_CLASS 0x34
39#define PCIE_LINK_STATUS 0x50
40
41#define PCIE_PORT_INT_EN(x) BIT(20 + (x))
42#define PCIE_PORT_PERST(x) BIT(1 + (x))
43#define PCIE_PORT_LINKUP BIT(0)
44#define PCIE_BAR_MAP_MAX GENMASK(31, 16)
45
46#define PCIE_BAR_ENABLE BIT(0)
47#define PCIE_REVISION_ID BIT(0)
48#define PCIE_CLASS_CODE (0x60400 << 8)
49#define PCIE_CONF_REG(regn) (((regn) & GENMASK(7, 2)) | \
50 ((((regn) >> 8) & GENMASK(3, 0)) << 24))
51#define PCIE_CONF_FUN(fun) (((fun) << 8) & GENMASK(10, 8))
52#define PCIE_CONF_DEV(dev) (((dev) << 11) & GENMASK(15, 11))
53#define PCIE_CONF_BUS(bus) (((bus) << 16) & GENMASK(23, 16))
54#define PCIE_CONF_ADDR(regn, fun, dev, bus) \
55 (PCIE_CONF_REG(regn) | PCIE_CONF_FUN(fun) | \
56 PCIE_CONF_DEV(dev) | PCIE_CONF_BUS(bus))
57
58/* MediaTek specific configuration registers */
59#define PCIE_FTS_NUM 0x70c
60#define PCIE_FTS_NUM_MASK GENMASK(15, 8)
61#define PCIE_FTS_NUM_L0(x) ((x) & 0xff << 8)
62
63#define PCIE_FC_CREDIT 0x73c
64#define PCIE_FC_CREDIT_MASK (GENMASK(31, 31) | GENMASK(28, 16))
65#define PCIE_FC_CREDIT_VAL(x) ((x) << 16)
66
Honghui Zhangc681c932017-08-10 14:34:56 +080067struct mtk_pcie_port;
68
69/**
70 * struct mtk_pcie_soc - differentiate between host generations
71 * @ops: pointer to configuration access functions
72 * @startup: pointer to controller setting functions
73 */
74struct mtk_pcie_soc {
75 struct pci_ops *ops;
76 int (*startup)(struct mtk_pcie_port *port);
77};
78
Ryder Lee637cfaca2017-05-21 11:42:24 +080079/**
80 * struct mtk_pcie_port - PCIe port information
81 * @base: IO mapped register base
82 * @list: port list
83 * @pcie: pointer to PCIe host info
84 * @reset: pointer to port reset control
85 * @sys_ck: pointer to bus clock
86 * @phy: pointer to phy control block
87 * @lane: lane count
Honghui Zhang4f6f0462017-08-10 14:34:55 +080088 * @slot: port slot
Ryder Lee637cfaca2017-05-21 11:42:24 +080089 */
90struct mtk_pcie_port {
91 void __iomem *base;
92 struct list_head list;
93 struct mtk_pcie *pcie;
94 struct reset_control *reset;
95 struct clk *sys_ck;
96 struct phy *phy;
97 u32 lane;
Honghui Zhang4f6f0462017-08-10 14:34:55 +080098 u32 slot;
Ryder Lee637cfaca2017-05-21 11:42:24 +080099};
100
101/**
102 * struct mtk_pcie - PCIe host information
103 * @dev: pointer to PCIe device
104 * @base: IO mapped register base
105 * @free_ck: free-run reference clock
106 * @io: IO resource
107 * @pio: PIO resource
108 * @mem: non-prefetchable memory resource
109 * @busn: bus range
110 * @offset: IO / Memory offset
111 * @ports: pointer to PCIe port information
Honghui Zhangc681c932017-08-10 14:34:56 +0800112 * @soc: pointer to SoC-dependent operations
Ryder Lee637cfaca2017-05-21 11:42:24 +0800113 */
114struct mtk_pcie {
115 struct device *dev;
116 void __iomem *base;
117 struct clk *free_ck;
118
119 struct resource io;
120 struct resource pio;
121 struct resource mem;
122 struct resource busn;
123 struct {
124 resource_size_t mem;
125 resource_size_t io;
126 } offset;
127 struct list_head ports;
Honghui Zhangc681c932017-08-10 14:34:56 +0800128 const struct mtk_pcie_soc *soc;
Ryder Lee637cfaca2017-05-21 11:42:24 +0800129};
130
Ryder Lee637cfaca2017-05-21 11:42:24 +0800131static void mtk_pcie_subsys_powerdown(struct mtk_pcie *pcie)
132{
133 struct device *dev = pcie->dev;
134
135 clk_disable_unprepare(pcie->free_ck);
136
137 if (dev->pm_domain) {
138 pm_runtime_put_sync(dev);
139 pm_runtime_disable(dev);
140 }
141}
142
143static void mtk_pcie_port_free(struct mtk_pcie_port *port)
144{
145 struct mtk_pcie *pcie = port->pcie;
146 struct device *dev = pcie->dev;
147
148 devm_iounmap(dev, port->base);
149 list_del(&port->list);
150 devm_kfree(dev, port);
151}
152
153static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
154{
155 struct mtk_pcie_port *port, *tmp;
156
157 list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
158 phy_power_off(port->phy);
159 clk_disable_unprepare(port->sys_ck);
160 mtk_pcie_port_free(port);
161 }
162
163 mtk_pcie_subsys_powerdown(pcie);
164}
165
166static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
167 unsigned int devfn, int where)
168{
169 struct pci_host_bridge *host = pci_find_host_bridge(bus);
170 struct mtk_pcie *pcie = pci_host_bridge_priv(host);
171
172 writel(PCIE_CONF_ADDR(where, PCI_FUNC(devfn), PCI_SLOT(devfn),
173 bus->number), pcie->base + PCIE_CFG_ADDR);
174
175 return pcie->base + PCIE_CFG_DATA + (where & 3);
176}
177
178static struct pci_ops mtk_pcie_ops = {
179 .map_bus = mtk_pcie_map_bus,
180 .read = pci_generic_config_read,
181 .write = pci_generic_config_write,
182};
183
Ryder Leee10b7a12017-08-10 14:34:54 +0800184static int mtk_pcie_startup_port(struct mtk_pcie_port *port)
Ryder Lee637cfaca2017-05-21 11:42:24 +0800185{
186 struct mtk_pcie *pcie = port->pcie;
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800187 u32 func = PCI_FUNC(port->slot << 3);
188 u32 slot = PCI_SLOT(port->slot << 3);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800189 u32 val;
Ryder Leee10b7a12017-08-10 14:34:54 +0800190 int err;
191
192 /* assert port PERST_N */
193 val = readl(pcie->base + PCIE_SYS_CFG);
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800194 val |= PCIE_PORT_PERST(port->slot);
Ryder Leee10b7a12017-08-10 14:34:54 +0800195 writel(val, pcie->base + PCIE_SYS_CFG);
196
197 /* de-assert port PERST_N */
198 val = readl(pcie->base + PCIE_SYS_CFG);
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800199 val &= ~PCIE_PORT_PERST(port->slot);
Ryder Leee10b7a12017-08-10 14:34:54 +0800200 writel(val, pcie->base + PCIE_SYS_CFG);
201
202 /* 100ms timeout value should be enough for Gen1/2 training */
203 err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
204 !!(val & PCIE_PORT_LINKUP), 20,
205 100 * USEC_PER_MSEC);
206 if (err)
207 return -ETIMEDOUT;
Ryder Lee637cfaca2017-05-21 11:42:24 +0800208
209 /* enable interrupt */
210 val = readl(pcie->base + PCIE_INT_ENABLE);
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800211 val |= PCIE_PORT_INT_EN(port->slot);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800212 writel(val, pcie->base + PCIE_INT_ENABLE);
213
214 /* map to all DDR region. We need to set it before cfg operation. */
215 writel(PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE,
216 port->base + PCIE_BAR0_SETUP);
217
218 /* configure class code and revision ID */
219 writel(PCIE_CLASS_CODE | PCIE_REVISION_ID, port->base + PCIE_CLASS);
220
221 /* configure FC credit */
222 writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, func, slot, 0),
223 pcie->base + PCIE_CFG_ADDR);
224 val = readl(pcie->base + PCIE_CFG_DATA);
225 val &= ~PCIE_FC_CREDIT_MASK;
226 val |= PCIE_FC_CREDIT_VAL(0x806c);
227 writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, func, slot, 0),
228 pcie->base + PCIE_CFG_ADDR);
229 writel(val, pcie->base + PCIE_CFG_DATA);
230
231 /* configure RC FTS number to 250 when it leaves L0s */
232 writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
233 pcie->base + PCIE_CFG_ADDR);
234 val = readl(pcie->base + PCIE_CFG_DATA);
235 val &= ~PCIE_FTS_NUM_MASK;
236 val |= PCIE_FTS_NUM_L0(0x50);
237 writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
238 pcie->base + PCIE_CFG_ADDR);
239 writel(val, pcie->base + PCIE_CFG_DATA);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800240
Ryder Leee10b7a12017-08-10 14:34:54 +0800241 return 0;
Ryder Lee637cfaca2017-05-21 11:42:24 +0800242}
243
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800244static void mtk_pcie_enable_port(struct mtk_pcie_port *port)
Ryder Lee637cfaca2017-05-21 11:42:24 +0800245{
Honghui Zhangc681c932017-08-10 14:34:56 +0800246 struct mtk_pcie *pcie = port->pcie;
247 struct device *dev = pcie->dev;
Ryder Lee637cfaca2017-05-21 11:42:24 +0800248 int err;
249
250 err = clk_prepare_enable(port->sys_ck);
251 if (err) {
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800252 dev_err(dev, "failed to enable port%d clock\n", port->slot);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800253 goto err_sys_clk;
254 }
255
256 reset_control_assert(port->reset);
257 reset_control_deassert(port->reset);
258
259 err = phy_power_on(port->phy);
260 if (err) {
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800261 dev_err(dev, "failed to power on port%d phy\n", port->slot);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800262 goto err_phy_on;
263 }
264
Honghui Zhangc681c932017-08-10 14:34:56 +0800265 if (!pcie->soc->startup(port))
Ryder Lee637cfaca2017-05-21 11:42:24 +0800266 return;
Ryder Lee637cfaca2017-05-21 11:42:24 +0800267
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800268 dev_info(dev, "Port%d link down\n", port->slot);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800269
270 phy_power_off(port->phy);
271err_phy_on:
272 clk_disable_unprepare(port->sys_ck);
273err_sys_clk:
274 mtk_pcie_port_free(port);
275}
276
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800277static int mtk_pcie_parse_port(struct mtk_pcie *pcie,
278 struct device_node *node,
279 int slot)
Ryder Lee637cfaca2017-05-21 11:42:24 +0800280{
281 struct mtk_pcie_port *port;
282 struct resource *regs;
283 struct device *dev = pcie->dev;
284 struct platform_device *pdev = to_platform_device(dev);
285 char name[10];
286 int err;
287
288 port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
289 if (!port)
290 return -ENOMEM;
291
292 err = of_property_read_u32(node, "num-lanes", &port->lane);
293 if (err) {
294 dev_err(dev, "missing num-lanes property\n");
295 return err;
296 }
297
Ryder Lee1eacd7b2017-08-10 14:34:57 +0800298 snprintf(name, sizeof(name), "port%d", slot);
299 regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800300 port->base = devm_ioremap_resource(dev, regs);
301 if (IS_ERR(port->base)) {
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800302 dev_err(dev, "failed to map port%d base\n", slot);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800303 return PTR_ERR(port->base);
304 }
305
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800306 snprintf(name, sizeof(name), "sys_ck%d", slot);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800307 port->sys_ck = devm_clk_get(dev, name);
308 if (IS_ERR(port->sys_ck)) {
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800309 dev_err(dev, "failed to get port%d clock\n", slot);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800310 return PTR_ERR(port->sys_ck);
311 }
312
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800313 snprintf(name, sizeof(name), "pcie-rst%d", slot);
Philipp Zabel608fcac2017-07-19 17:26:00 +0200314 port->reset = devm_reset_control_get_optional_exclusive(dev, name);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800315 if (PTR_ERR(port->reset) == -EPROBE_DEFER)
316 return PTR_ERR(port->reset);
317
318 /* some platforms may use default PHY setting */
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800319 snprintf(name, sizeof(name), "pcie-phy%d", slot);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800320 port->phy = devm_phy_optional_get(dev, name);
321 if (IS_ERR(port->phy))
322 return PTR_ERR(port->phy);
323
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800324 port->slot = slot;
Ryder Lee637cfaca2017-05-21 11:42:24 +0800325 port->pcie = pcie;
326
327 INIT_LIST_HEAD(&port->list);
328 list_add_tail(&port->list, &pcie->ports);
329
330 return 0;
331}
332
333static int mtk_pcie_subsys_powerup(struct mtk_pcie *pcie)
334{
335 struct device *dev = pcie->dev;
336 struct platform_device *pdev = to_platform_device(dev);
337 struct resource *regs;
338 int err;
339
Ryder Lee1eacd7b2017-08-10 14:34:57 +0800340 /* get shared registers, which are optional */
341 regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "subsys");
342 if (regs) {
343 pcie->base = devm_ioremap_resource(dev, regs);
344 if (IS_ERR(pcie->base)) {
345 dev_err(dev, "failed to map shared register\n");
346 return PTR_ERR(pcie->base);
347 }
Ryder Lee637cfaca2017-05-21 11:42:24 +0800348 }
349
350 pcie->free_ck = devm_clk_get(dev, "free_ck");
351 if (IS_ERR(pcie->free_ck)) {
352 if (PTR_ERR(pcie->free_ck) == -EPROBE_DEFER)
353 return -EPROBE_DEFER;
354
355 pcie->free_ck = NULL;
356 }
357
358 if (dev->pm_domain) {
359 pm_runtime_enable(dev);
360 pm_runtime_get_sync(dev);
361 }
362
363 /* enable top level clock */
364 err = clk_prepare_enable(pcie->free_ck);
365 if (err) {
366 dev_err(dev, "failed to enable free_ck\n");
367 goto err_free_ck;
368 }
369
370 return 0;
371
372err_free_ck:
373 if (dev->pm_domain) {
374 pm_runtime_put_sync(dev);
375 pm_runtime_disable(dev);
376 }
377
378 return err;
379}
380
381static int mtk_pcie_setup(struct mtk_pcie *pcie)
382{
383 struct device *dev = pcie->dev;
384 struct device_node *node = dev->of_node, *child;
385 struct of_pci_range_parser parser;
386 struct of_pci_range range;
387 struct resource res;
388 struct mtk_pcie_port *port, *tmp;
389 int err;
390
391 if (of_pci_range_parser_init(&parser, node)) {
392 dev_err(dev, "missing \"ranges\" property\n");
393 return -EINVAL;
394 }
395
396 for_each_of_pci_range(&parser, &range) {
397 err = of_pci_range_to_resource(&range, node, &res);
398 if (err < 0)
399 return err;
400
401 switch (res.flags & IORESOURCE_TYPE_BITS) {
402 case IORESOURCE_IO:
403 pcie->offset.io = res.start - range.pci_addr;
404
405 memcpy(&pcie->pio, &res, sizeof(res));
406 pcie->pio.name = node->full_name;
407
408 pcie->io.start = range.cpu_addr;
409 pcie->io.end = range.cpu_addr + range.size - 1;
410 pcie->io.flags = IORESOURCE_MEM;
411 pcie->io.name = "I/O";
412
413 memcpy(&res, &pcie->io, sizeof(res));
414 break;
415
416 case IORESOURCE_MEM:
417 pcie->offset.mem = res.start - range.pci_addr;
418
419 memcpy(&pcie->mem, &res, sizeof(res));
420 pcie->mem.name = "non-prefetchable";
421 break;
422 }
423 }
424
425 err = of_pci_parse_bus_range(node, &pcie->busn);
426 if (err < 0) {
427 dev_err(dev, "failed to parse bus ranges property: %d\n", err);
428 pcie->busn.name = node->name;
429 pcie->busn.start = 0;
430 pcie->busn.end = 0xff;
431 pcie->busn.flags = IORESOURCE_BUS;
432 }
433
434 for_each_available_child_of_node(node, child) {
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800435 int slot;
Ryder Lee637cfaca2017-05-21 11:42:24 +0800436
437 err = of_pci_get_devfn(child);
438 if (err < 0) {
439 dev_err(dev, "failed to parse devfn: %d\n", err);
440 return err;
441 }
442
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800443 slot = PCI_SLOT(err);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800444
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800445 err = mtk_pcie_parse_port(pcie, child, slot);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800446 if (err)
447 return err;
448 }
449
450 err = mtk_pcie_subsys_powerup(pcie);
451 if (err)
452 return err;
453
454 /* enable each port, and then check link status */
455 list_for_each_entry_safe(port, tmp, &pcie->ports, list)
Honghui Zhang4f6f0462017-08-10 14:34:55 +0800456 mtk_pcie_enable_port(port);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800457
458 /* power down PCIe subsys if slots are all empty (link down) */
459 if (list_empty(&pcie->ports))
460 mtk_pcie_subsys_powerdown(pcie);
461
462 return 0;
463}
464
465static int mtk_pcie_request_resources(struct mtk_pcie *pcie)
466{
467 struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
468 struct list_head *windows = &host->windows;
469 struct device *dev = pcie->dev;
470 int err;
471
472 pci_add_resource_offset(windows, &pcie->pio, pcie->offset.io);
473 pci_add_resource_offset(windows, &pcie->mem, pcie->offset.mem);
474 pci_add_resource(windows, &pcie->busn);
475
476 err = devm_request_pci_bus_resources(dev, windows);
477 if (err < 0)
478 return err;
479
480 pci_remap_iospace(&pcie->pio, pcie->io.start);
481
482 return 0;
483}
484
485static int mtk_pcie_register_host(struct pci_host_bridge *host)
486{
487 struct mtk_pcie *pcie = pci_host_bridge_priv(host);
488 struct pci_bus *child;
489 int err;
490
491 host->busnr = pcie->busn.start;
492 host->dev.parent = pcie->dev;
Honghui Zhangc681c932017-08-10 14:34:56 +0800493 host->ops = pcie->soc->ops;
Ryder Lee637cfaca2017-05-21 11:42:24 +0800494 host->map_irq = of_irq_parse_and_map_pci;
495 host->swizzle_irq = pci_common_swizzle;
496
497 err = pci_scan_root_bus_bridge(host);
498 if (err < 0)
499 return err;
500
501 pci_bus_size_bridges(host->bus);
502 pci_bus_assign_resources(host->bus);
503
504 list_for_each_entry(child, &host->bus->children, node)
505 pcie_bus_configure_settings(child);
506
507 pci_bus_add_devices(host->bus);
508
509 return 0;
510}
511
512static int mtk_pcie_probe(struct platform_device *pdev)
513{
514 struct device *dev = &pdev->dev;
515 struct mtk_pcie *pcie;
516 struct pci_host_bridge *host;
517 int err;
518
519 host = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
520 if (!host)
521 return -ENOMEM;
522
523 pcie = pci_host_bridge_priv(host);
524
525 pcie->dev = dev;
Honghui Zhangc681c932017-08-10 14:34:56 +0800526 pcie->soc = of_device_get_match_data(dev);
Ryder Lee637cfaca2017-05-21 11:42:24 +0800527 platform_set_drvdata(pdev, pcie);
528 INIT_LIST_HEAD(&pcie->ports);
529
530 err = mtk_pcie_setup(pcie);
531 if (err)
532 return err;
533
534 err = mtk_pcie_request_resources(pcie);
535 if (err)
536 goto put_resources;
537
538 err = mtk_pcie_register_host(host);
539 if (err)
540 goto put_resources;
541
542 return 0;
543
544put_resources:
545 if (!list_empty(&pcie->ports))
546 mtk_pcie_put_resources(pcie);
547
548 return err;
549}
550
Honghui Zhangc681c932017-08-10 14:34:56 +0800551static const struct mtk_pcie_soc mtk_pcie_soc_v1 = {
552 .ops = &mtk_pcie_ops,
553 .startup = mtk_pcie_startup_port,
554};
555
Ryder Lee637cfaca2017-05-21 11:42:24 +0800556static const struct of_device_id mtk_pcie_ids[] = {
Honghui Zhangc681c932017-08-10 14:34:56 +0800557 { .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
558 { .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
Ryder Lee637cfaca2017-05-21 11:42:24 +0800559 {},
560};
561
562static struct platform_driver mtk_pcie_driver = {
563 .probe = mtk_pcie_probe,
564 .driver = {
565 .name = "mtk-pcie",
566 .of_match_table = mtk_pcie_ids,
567 .suppress_bind_attrs = true,
568 },
569};
570builtin_platform_driver(mtk_pcie_driver);