blob: f717384e8fbe48cc50c06fe3b7dd451177316bf1 [file] [log] [blame]
Alexandru Gagniuc23211b02013-06-09 16:06:07 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
5 *
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.
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.
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050015 */
16
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>
22
23#include "vx900.h"
24
25/**
Martin Roth543888d2015-01-06 10:20:42 -070026 * @file vx900/pcie.c
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050027 *
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).
33 *
34 * There is currently no timeout detection mechanism for when a link comes up.
35 * If the link never comes up, we hang.
36 */
37
38static void vx900_pcie_link_init(device_t dev)
39{
40 u8 reg8;
41 u32 reg32;
42
43 u8 fn = dev->path.pci.devfn & 0x07;
44
45 /* Step 1 : Check for presence of PCIE device */
46 reg8 = pci_read_config8(dev, 0x5a);
47
48 if (reg8 & (1 << 6))
49 printk(BIOS_DEBUG, "Card detected in PEX%i\n", fn);
50 else
51 return;
52
53 /* Step 2: Wait for device to enter L0 state */
54 /* FIXME: implement timeout detection */
55 while (0x8a != pci_read_config8(dev, 0x1c3)) ;
56
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;
63 }
64
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);
69
70 pci_write_config8(dev, 0xa4, 0xff);
71 if (pci_read_config8(dev, 0x4a) & (1 << 3))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080072 printk(BIOS_DEBUG, "Unsupported request detected.\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050073
74 pci_write_config8(dev, 0x15a, 0xff);
75 if (pci_read_config8(dev, 0x15a) & (1 << 1))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080076 printk(BIOS_DEBUG, "Negotiation pending.\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050077
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? */
82}
83
84static void vx900_pex_dev_set_resources(device_t dev)
85{
86 assign_resources(dev->link_list);
87}
88
89static void vx900_pex_init(device_t dev)
90{
91 /* FIXME: For some reason, PEX0 hangs on init. Find issue, fix it. */
92 if ((dev->path.pci.devfn & 0x7) == 0)
93 return;
94
95 vx900_pcie_link_init(dev);
96}
97
98static 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,
105};
106
107static 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,
112 0,
113};
114
115static const struct pci_driver pex_driver __pci_driver = {
116 .ops = &vx900_pex_ops,
117 .vendor = PCI_VENDOR_ID_VIA,
118 .devices = pci_device_ids,
119
120};