nb/via/vx900: Get rid of device_t
[coreboot.git] / src / northbridge / via / vx900 / pcie.c
blob1d3ecd9938b5cc5282bae7e6597e922f03c6a93e
1 /*
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.
17 #include <arch/io.h>
18 #include <console/console.h>
19 #include <device/pci.h>
20 #include <device/pciexp.h>
21 #include <device/pci_ids.h>
23 #include "vx900.h"
25 /**
26 * @file vx900/pcie.c
28 * STATUS:
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)
40 u8 reg8;
41 u32 reg32;
43 u8 fn = dev->path.pci.devfn & 0x07;
45 /* Step 1 : Check for presence of PCIE device */
46 reg8 = pci_read_config8(dev, 0x5a);
48 if (reg8 & (1 << 6))
49 printk(BIOS_DEBUG, "Card detected in PEX%i\n", fn);
50 else
51 return;
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);
60 if (0 != reg32) {
61 printk(BIOS_DEBUG, "PEX init error. flags 0x%.8x\n", reg32);
62 return;
65 pci_write_config32(dev, 0x110, 0xffffffff);
66 reg32 = pci_read_config32(dev, 0x110);
67 if (0 != reg32)
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
81 * time? */
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)
93 return;
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,