2 * This file is part of the coreboot project.
4 * Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
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.
18 #include <console/console.h>
19 #include <device/pci.h>
20 #include <device/pciexp.h>
21 #include <device/pci_ids.h>
29 * We do part of the sequence to initialize the PCIE link. The problem is that
30 * the reset signal for each slot is connected to a GPO pin, but We don't know
31 * which GPO pin. We need to figure out which GPIO pin is hooked to which slot,
32 * and have a mechanism to specify this per-mainboard (devicetree.cb).
34 * There is currently no timeout detection mechanism for when a link comes up.
35 * If the link never comes up, we hang.
38 static void vx900_pcie_link_init(struct device
*dev
)
43 u8 fn
= dev
->path
.pci
.devfn
& 0x07;
45 /* Step 1 : Check for presence of PCIE device */
46 reg8
= pci_read_config8(dev
, 0x5a);
49 printk(BIOS_DEBUG
, "Card detected in PEX%i\n", fn
);
53 /* Step 2: Wait for device to enter L0 state */
54 /* FIXME: implement timeout detection */
55 while (0x8a != pci_read_config8(dev
, 0x1c3));
57 /* Step 3: Clear PCIe error status, then check for failures */
58 pci_write_config32(dev
, 0x104, 0xffffffff);
59 reg32
= pci_read_config32(dev
, 0x104);
61 printk(BIOS_DEBUG
, "PEX init error. flags 0x%.8x\n", reg32
);
65 pci_write_config32(dev
, 0x110, 0xffffffff);
66 reg32
= pci_read_config32(dev
, 0x110);
68 printk(BIOS_DEBUG
, "PEX errors. flags 0x%.8x\n", reg32
);
70 pci_write_config8(dev
, 0xa4, 0xff);
71 if (pci_read_config8(dev
, 0x4a) & (1 << 3))
72 printk(BIOS_DEBUG
, "Unsupported request detected.\n");
74 pci_write_config8(dev
, 0x15a, 0xff);
75 if (pci_read_config8(dev
, 0x15a) & (1 << 1))
76 printk(BIOS_DEBUG
, "Negotiation pending.\n");
78 /* Step 4: Read vendor ID */
79 /* FIXME: Do we want to run through the whole sequence and delay boot
80 * by several seconds if the device does not respond properly the first
84 static void vx900_pex_dev_set_resources(struct device
*dev
)
86 assign_resources(dev
->link_list
);
89 static void vx900_pex_init(struct device
*dev
)
91 /* FIXME: For some reason, PEX0 hangs on init. Find issue, fix it. */
92 if ((dev
->path
.pci
.devfn
& 0x7) == 0)
95 vx900_pcie_link_init(dev
);
98 static struct device_operations vx900_pex_ops
= {
99 .read_resources
= pci_bus_read_resources
,
100 .set_resources
= vx900_pex_dev_set_resources
,
101 .enable_resources
= pci_bus_enable_resources
,
102 .init
= vx900_pex_init
,
103 .scan_bus
= pciexp_scan_bridge
,
104 .reset_bus
= pci_bus_reset
,
107 static const unsigned short pci_device_ids
[] = {
108 PCI_DEVICE_ID_VIA_VX900_PEX1
,
109 PCI_DEVICE_ID_VIA_VX900_PEX2
,
110 PCI_DEVICE_ID_VIA_VX900_PEX3
,
111 PCI_DEVICE_ID_VIA_VX900_PEX4
,
115 static const struct pci_driver pex_driver __pci_driver
= {
116 .ops
= &vx900_pex_ops
,
117 .vendor
= PCI_VENDOR_ID_VIA
,
118 .devices
= pci_device_ids
,