blob: 472adfc1a0174da33347fb3657a8808c130a135d [file] [log] [blame]
Stefan Reinauer7ce8c542005-12-02 21:52:30 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Uwe Hermannb80dbf02007-04-22 19:08:13 +00003 *
4 * Copyright (C) 2003-2004 Linux Networx
5 * (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx)
6 * Copyright (C) 2004 David Hendricks <sc@flagen.com>
7 * Copyright (C) 2004 Li-Ta Lo <ollie@lanl.gov>
8 * Copyright (C) 2005-2006 Tyan
9 * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
10 * Copyright (C) 2005-2006 Stefan Reinauer <stepan@openbios.org>
Timothy Pearsona690a782015-09-05 18:06:52 -050011 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
Uwe Hermannb80dbf02007-04-22 19:08:13 +000012 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; version 2 of the License.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
Uwe Hermannb80dbf02007-04-22 19:08:13 +000021 */
Stefan Reinauer7ce8c542005-12-02 21:52:30 +000022
Ronald G. Minnich5079a0d2012-11-27 11:32:38 -080023#include <lib.h>
Eric Biederman0ac6b412003-09-02 17:16:48 +000024#include <console/console.h>
25#include <device/device.h>
26#include <device/path.h>
27#include <device/pci.h>
Eric Biederman5cd81732004-03-11 15:01:31 +000028#include <device/pci_ids.h>
Eric Biedermanff0e8462003-09-04 03:00:54 +000029#include <device/hypertransport.h>
Eric Biederman0ac6b412003-09-02 17:16:48 +000030
Kyösti Mälkkic3f6bb02015-02-03 12:18:02 +020031struct ht_link {
32 struct device *dev;
33 unsigned pos;
34 unsigned char ctrl_off, config_off, freq_off, freq_cap_off;
35};
arch import user (historical)ef03afa2005-07-06 17:15:30 +000036
Eric Biederman0ac6b412003-09-02 17:16:48 +000037static device_t ht_scan_get_devs(device_t *old_devices)
38{
39 device_t first, last;
Uwe Hermanne4870472010-11-04 23:23:47 +000040
Eric Biederman0ac6b412003-09-02 17:16:48 +000041 first = *old_devices;
42 last = first;
Uwe Hermanne4870472010-11-04 23:23:47 +000043
44 /*
45 * Extract the chain of devices to (first through last) for the next
46 * hypertransport device.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000047 */
Uwe Hermanne4870472010-11-04 23:23:47 +000048 while (last && last->sibling &&
49 (last->sibling->path.type == DEVICE_PATH_PCI) &&
50 (last->sibling->path.pci.devfn > last->path.pci.devfn))
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000051 {
Eric Biederman0ac6b412003-09-02 17:16:48 +000052 last = last->sibling;
53 }
Uwe Hermanne4870472010-11-04 23:23:47 +000054
Eric Biederman0ac6b412003-09-02 17:16:48 +000055 if (first) {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000056 device_t child;
Uwe Hermanne4870472010-11-04 23:23:47 +000057
58 /* Unlink the chain from the list of old devices. */
Eric Biederman0ac6b412003-09-02 17:16:48 +000059 *old_devices = last->sibling;
60 last->sibling = 0;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000061
Uwe Hermanne4870472010-11-04 23:23:47 +000062 /* Now add the device to the list of devices on the bus. */
63 /* Find the last child of our parent. */
64 for (child = first->bus->children; child && child->sibling; )
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000065 child = child->sibling;
Uwe Hermanne4870472010-11-04 23:23:47 +000066
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000067 /* Place the chain on the list of children of their parent. */
Uwe Hermanne4870472010-11-04 23:23:47 +000068 if (child)
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000069 child->sibling = first;
Uwe Hermanne4870472010-11-04 23:23:47 +000070 else
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000071 first->bus->children = first;
Eric Biederman0ac6b412003-09-02 17:16:48 +000072 }
73 return first;
74}
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000075
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000076static int ht_setup_link(struct ht_link *prev, device_t dev, unsigned pos)
Eric Biederman0ac6b412003-09-02 17:16:48 +000077{
Stefan Reinauer0dff6e32007-10-23 22:17:45 +000078 struct ht_link cur[1];
Yinghai Lu1f1085b2005-01-17 21:37:12 +000079 int linkb_to_host;
Eric Biederman0ac6b412003-09-02 17:16:48 +000080
Uwe Hermanne4870472010-11-04 23:23:47 +000081 /* Set the hypertransport link width and frequency. */
Kyösti Mälkkic3f6bb02015-02-03 12:18:02 +020082
Uwe Hermanne4870472010-11-04 23:23:47 +000083 /*
84 * See which side of the device our previous write to set the unitid
85 * came from.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000086 */
87 cur->dev = dev;
88 cur->pos = pos;
Uwe Hermanne4870472010-11-04 23:23:47 +000089 linkb_to_host =
90 (pci_read_config16(cur->dev, cur->pos + PCI_CAP_FLAGS) >> 10) & 1;
91
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000092 if (!linkb_to_host) {
93 cur->ctrl_off = PCI_HT_CAP_SLAVE_CTRL0;
94 cur->config_off = PCI_HT_CAP_SLAVE_WIDTH0;
95 cur->freq_off = PCI_HT_CAP_SLAVE_FREQ0;
96 cur->freq_cap_off = PCI_HT_CAP_SLAVE_FREQ_CAP0;
Uwe Hermanne4870472010-11-04 23:23:47 +000097 } else {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000098 cur->ctrl_off = PCI_HT_CAP_SLAVE_CTRL1;
99 cur->config_off = PCI_HT_CAP_SLAVE_WIDTH1;
100 cur->freq_off = PCI_HT_CAP_SLAVE_FREQ1;
101 cur->freq_cap_off = PCI_HT_CAP_SLAVE_FREQ_CAP1;
102 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000103
Uwe Hermanne4870472010-11-04 23:23:47 +0000104 /*
105 * Remember the current link as the previous link, but look at the
106 * other offsets.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000107 */
108 prev->dev = cur->dev;
109 prev->pos = cur->pos;
110 if (cur->ctrl_off == PCI_HT_CAP_SLAVE_CTRL0) {
111 prev->ctrl_off = PCI_HT_CAP_SLAVE_CTRL1;
112 prev->config_off = PCI_HT_CAP_SLAVE_WIDTH1;
113 prev->freq_off = PCI_HT_CAP_SLAVE_FREQ1;
114 prev->freq_cap_off = PCI_HT_CAP_SLAVE_FREQ_CAP1;
115 } else {
116 prev->ctrl_off = PCI_HT_CAP_SLAVE_CTRL0;
117 prev->config_off = PCI_HT_CAP_SLAVE_WIDTH0;
118 prev->freq_off = PCI_HT_CAP_SLAVE_FREQ0;
119 prev->freq_cap_off = PCI_HT_CAP_SLAVE_FREQ_CAP0;
120 }
Eric Biederman0ac6b412003-09-02 17:16:48 +0000121
Kyösti Mälkkic3f6bb02015-02-03 12:18:02 +0200122 return 0;
Eric Biederman0ac6b412003-09-02 17:16:48 +0000123}
124
125static unsigned ht_lookup_slave_capability(struct device *dev)
126{
127 unsigned pos;
Uwe Hermanne4870472010-11-04 23:23:47 +0000128
Eric Biederman0ac6b412003-09-02 17:16:48 +0000129 pos = 0;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000130 do {
131 pos = pci_find_next_capability(dev, PCI_CAP_ID_HT, pos);
132 if (pos) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000133 u16 flags;
Eric Biederman0ac6b412003-09-02 17:16:48 +0000134 flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000135 printk(BIOS_SPEW, "flags: 0x%04x\n", flags);
Eric Biederman0ac6b412003-09-02 17:16:48 +0000136 if ((flags >> 13) == 0) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000137 /* Entry is a slave secondary, success... */
Eric Biederman0ac6b412003-09-02 17:16:48 +0000138 break;
139 }
140 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000141 } while (pos);
142
Eric Biederman0ac6b412003-09-02 17:16:48 +0000143 return pos;
144}
145
Uwe Hermanne4870472010-11-04 23:23:47 +0000146static void ht_collapse_early_enumeration(struct bus *bus,
147 unsigned offset_unitid)
Eric Biederman0ac6b412003-09-02 17:16:48 +0000148{
149 unsigned int devfn;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000150 struct ht_link prev;
Uwe Hermanne4870472010-11-04 23:23:47 +0000151 u16 ctrl;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000152
Uwe Hermanne4870472010-11-04 23:23:47 +0000153 /* Initialize the hypertransport enumeration state. */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000154 prev.dev = bus->dev;
155 prev.pos = bus->cap;
156 prev.ctrl_off = PCI_HT_CAP_HOST_CTRL;
157 prev.config_off = PCI_HT_CAP_HOST_WIDTH;
158 prev.freq_off = PCI_HT_CAP_HOST_FREQ;
159 prev.freq_cap_off = PCI_HT_CAP_HOST_FREQ_CAP;
160
Uwe Hermanne4870472010-11-04 23:23:47 +0000161 /* Wait until the link initialization is complete. */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000162 do {
163 ctrl = pci_read_config16(prev.dev, prev.pos + prev.ctrl_off);
Uwe Hermanne4870472010-11-04 23:23:47 +0000164
165 /* Is this the end of the hypertransport chain? */
166 if (ctrl & (1 << 6))
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000167 return;
Uwe Hermanne4870472010-11-04 23:23:47 +0000168
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000169 /* Has the link failed? */
170 if (ctrl & (1 << 4)) {
Stefan Reinauercf648c92006-04-11 19:23:57 +0000171 /*
Uwe Hermanne4870472010-11-04 23:23:47 +0000172 * Either the link has failed, or we have a CRC error.
173 * Sometimes this can happen due to link retrain, so
174 * lets knock it down and see if its transient.
Stefan Reinauercf648c92006-04-11 19:23:57 +0000175 */
Uwe Hermanne4870472010-11-04 23:23:47 +0000176 ctrl |= ((1 << 4) | (1 << 8)); /* Link fail + CRC */
177 pci_write_config16(prev.dev, prev.pos + prev.ctrl_off,
178 ctrl);
179 ctrl = pci_read_config16(prev.dev,
180 prev.pos + prev.ctrl_off);
Stefan Reinauercf648c92006-04-11 19:23:57 +0000181 if (ctrl & ((1 << 4) | (1 << 8))) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000182 printk(BIOS_ALERT, "Detected error on "
183 "Hypertransport link\n");
Stefan Reinauercf648c92006-04-11 19:23:57 +0000184 return;
185 }
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000186 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000187 } while ((ctrl & (1 << 5)) == 0);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000188
Uwe Hermanne4870472010-11-04 23:23:47 +0000189 /* Actually, only for one HT device HT chain, and unitid is 0. */
Patrick Georgie1667822012-05-05 15:29:32 +0200190#if !CONFIG_HT_CHAIN_UNITID_BASE
Uwe Hermanne4870472010-11-04 23:23:47 +0000191 if (offset_unitid)
192 return;
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000193#endif
194
Uwe Hermanne4870472010-11-04 23:23:47 +0000195 /* Check if is already collapsed. */
196 if ((!offset_unitid) || (offset_unitid
197 && (!((CONFIG_HT_CHAIN_END_UNITID_BASE == 0)
198 && (CONFIG_HT_CHAIN_END_UNITID_BASE
199 < CONFIG_HT_CHAIN_UNITID_BASE))))) {
Eric Biederman0ac6b412003-09-02 17:16:48 +0000200
Eric Biederman0ac6b412003-09-02 17:16:48 +0000201 struct device dummy;
Uwe Hermanne4870472010-11-04 23:23:47 +0000202 u32 id;
203
204 dummy.bus = bus;
205 dummy.path.type = DEVICE_PATH_PCI;
206 dummy.path.pci.devfn = PCI_DEVFN(0, 0);
207
Eric Biederman0ac6b412003-09-02 17:16:48 +0000208 id = pci_read_config32(&dummy, PCI_VENDOR_ID);
Uwe Hermanne4870472010-11-04 23:23:47 +0000209 if (!((id == 0xffffffff) || (id == 0x00000000)
210 || (id == 0x0000ffff) || (id == 0xffff0000))) {
211 return;
212 }
213 }
214
215 /* Spin through the devices and collapse any early HT enumeration. */
216 for (devfn = PCI_DEVFN(1, 0); devfn <= 0xff; devfn += 8) {
217 struct device dummy;
218 u32 id;
219 unsigned pos, flags;
220
221 dummy.bus = bus;
222 dummy.path.type = DEVICE_PATH_PCI;
223 dummy.path.pci.devfn = devfn;
224
225 id = pci_read_config32(&dummy, PCI_VENDOR_ID);
226 if ((id == 0xffffffff) || (id == 0x00000000)
227 || (id == 0x0000ffff) || (id == 0xffff0000)) {
Eric Biederman0ac6b412003-09-02 17:16:48 +0000228 continue;
229 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000230
Eric Biederman0ac6b412003-09-02 17:16:48 +0000231 dummy.vendor = id & 0xffff;
232 dummy.device = (id >> 16) & 0xffff;
233 dummy.hdr_type = pci_read_config8(&dummy, PCI_HEADER_TYPE);
Eric Biederman0ac6b412003-09-02 17:16:48 +0000234
Uwe Hermanne4870472010-11-04 23:23:47 +0000235 pos = ht_lookup_slave_capability(&dummy);
236 if (!pos)
237 continue;
238
239 /* Clear the unitid. */
Eric Biederman0ac6b412003-09-02 17:16:48 +0000240 flags = pci_read_config16(&dummy, pos + PCI_CAP_FLAGS);
241 flags &= ~0x1f;
242 pci_write_config16(&dummy, pos + PCI_CAP_FLAGS, flags);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000243 printk(BIOS_SPEW, "Collapsing %s [%04x/%04x]\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000244 dev_path(&dummy), dummy.vendor, dummy.device);
Eric Biederman0ac6b412003-09-02 17:16:48 +0000245 }
246}
247
Kyösti Mälkkied7bc2c2015-02-22 08:27:13 +0200248static unsigned int do_hypertransport_scan_chain(struct bus *bus, unsigned min_devfn,
Kyösti Mälkkib39714e2015-03-12 16:16:59 +0200249 unsigned max_devfn,
Uwe Hermanne4870472010-11-04 23:23:47 +0000250 unsigned *ht_unitid_base,
251 unsigned offset_unitid)
Eric Biederman0ac6b412003-09-02 17:16:48 +0000252{
Uwe Hermanne4870472010-11-04 23:23:47 +0000253 /*
254 * Even CONFIG_HT_CHAIN_UNITID_BASE == 0, we still can go through this
255 * function, because of end_of_chain check. Also, we need it to
256 * optimize link.
257 */
258 unsigned int next_unitid, last_unitid, min_unitid, max_unitid;
259 device_t old_devices, dev, func, last_func = 0;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000260 struct ht_link prev;
Stefan Reinauerbbdd8f42005-12-04 21:52:58 +0000261 int ht_dev_num = 0;
Uwe Hermanne4870472010-11-04 23:23:47 +0000262
Timothy Pearsona690a782015-09-05 18:06:52 -0500263 printk(BIOS_SPEW, "%s for bus %02x\n", __func__, bus->secondary);
264
Uwe Hermanne4870472010-11-04 23:23:47 +0000265 min_unitid = (offset_unitid) ? CONFIG_HT_CHAIN_UNITID_BASE : 1;
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000266
Stefan Reinauer08670622009-06-30 15:17:49 +0000267#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
Uwe Hermanne4870472010-11-04 23:23:47 +0000268 /*
269 * Let's record the device of last HT device, so we can set the unitid
270 * to CONFIG_HT_CHAIN_END_UNITID_BASE.
271 */
272 unsigned int real_last_unitid = 0, end_used = 0;
273 u8 real_last_pos = 0;
274 device_t real_last_dev = NULL;
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000275#endif
Eric Biederman0ac6b412003-09-02 17:16:48 +0000276
Martin Roth63373ed2013-07-08 16:24:19 -0600277 /* Restore the hypertransport chain to it's uninitialized state. */
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000278 ht_collapse_early_enumeration(bus, offset_unitid);
Eric Biederman0ac6b412003-09-02 17:16:48 +0000279
Uwe Hermanne4870472010-11-04 23:23:47 +0000280 /* See which static device nodes I have. */
Eric Biederman0ac6b412003-09-02 17:16:48 +0000281 old_devices = bus->children;
282 bus->children = 0;
Eric Biederman0ac6b412003-09-02 17:16:48 +0000283
Uwe Hermanne4870472010-11-04 23:23:47 +0000284 /* Initialize the hypertransport enumeration state. */
Eric Biederman0ac6b412003-09-02 17:16:48 +0000285 prev.dev = bus->dev;
286 prev.pos = bus->cap;
Uwe Hermanne4870472010-11-04 23:23:47 +0000287
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000288 prev.ctrl_off = PCI_HT_CAP_HOST_CTRL;
Eric Biederman0ac6b412003-09-02 17:16:48 +0000289 prev.config_off = PCI_HT_CAP_HOST_WIDTH;
290 prev.freq_off = PCI_HT_CAP_HOST_FREQ;
291 prev.freq_cap_off = PCI_HT_CAP_HOST_FREQ_CAP;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000292
Uwe Hermanne4870472010-11-04 23:23:47 +0000293 /* If present, assign unitid to a hypertransport chain. */
Eric Biederman0ac6b412003-09-02 17:16:48 +0000294 last_unitid = min_unitid -1;
Yinghai Lu18c70d72007-09-14 14:58:33 +0000295 max_unitid = next_unitid = min_unitid;
Eric Biederman0ac6b412003-09-02 17:16:48 +0000296 do {
Uwe Hermanne4870472010-11-04 23:23:47 +0000297 u8 pos;
298 u16 flags, ctrl;
299 unsigned int count, static_count;
Eric Biederman0ac6b412003-09-02 17:16:48 +0000300
Eric Biederman0ac6b412003-09-02 17:16:48 +0000301 last_unitid = next_unitid;
302
Uwe Hermanne4870472010-11-04 23:23:47 +0000303 /* Wait until the link initialization is complete. */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000304 do {
Uwe Hermanne4870472010-11-04 23:23:47 +0000305 ctrl = pci_read_config16(prev.dev,
306 prev.pos + prev.ctrl_off);
Stefan Reinauercf648c92006-04-11 19:23:57 +0000307
Uwe Hermanne4870472010-11-04 23:23:47 +0000308 /* End of chain? */
Stefan Reinauercf648c92006-04-11 19:23:57 +0000309 if (ctrl & (1 << 6))
Uwe Hermanne4870472010-11-04 23:23:47 +0000310 goto end_of_chain;
Stefan Reinauercf648c92006-04-11 19:23:57 +0000311
312 if (ctrl & ((1 << 4) | (1 << 8))) {
313 /*
Uwe Hermanne4870472010-11-04 23:23:47 +0000314 * Either the link has failed, or we have a CRC
315 * error. Sometimes this can happen due to link
316 * retrain, so lets knock it down and see if
317 * it's transient.
Stefan Reinauercf648c92006-04-11 19:23:57 +0000318 */
Uwe Hermanne4870472010-11-04 23:23:47 +0000319 ctrl |= ((1 << 4) | (1 <<8)); // Link fail + CRC
320 pci_write_config16(prev.dev,
321 prev.pos + prev.ctrl_off, ctrl);
322 ctrl = pci_read_config16(prev.dev,
323 prev.pos + prev.ctrl_off);
Stefan Reinauercf648c92006-04-11 19:23:57 +0000324 if (ctrl & ((1 << 4) | (1 << 8))) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000325 printk(BIOS_ALERT, "Detected error on "
326 "hypertransport link\n");
Stefan Reinauercf648c92006-04-11 19:23:57 +0000327 goto end_of_chain;
328 }
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000329 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000330 } while ((ctrl & (1 << 5)) == 0);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000331
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000332
Uwe Hermanne4870472010-11-04 23:23:47 +0000333 /* Get and setup the device_structure. */
Eric Biederman0ac6b412003-09-02 17:16:48 +0000334 dev = ht_scan_get_devs(&old_devices);
335
Uwe Hermanne4870472010-11-04 23:23:47 +0000336 /* See if a device is present and setup the device structure. */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000337 dev = pci_probe_dev(dev, bus, 0);
Uwe Hermanne4870472010-11-04 23:23:47 +0000338 if (!dev || !dev->enabled)
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000339 break;
Eric Biederman0ac6b412003-09-02 17:16:48 +0000340
Uwe Hermanne4870472010-11-04 23:23:47 +0000341 /* Find the hypertransport link capability. */
Eric Biederman0ac6b412003-09-02 17:16:48 +0000342 pos = ht_lookup_slave_capability(dev);
343 if (pos == 0) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000344 printk(BIOS_ERR, "%s Hypertransport link capability "
345 "not found", dev_path(dev));
Eric Biederman0ac6b412003-09-02 17:16:48 +0000346 break;
347 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000348
Uwe Hermanne4870472010-11-04 23:23:47 +0000349 /* Update the unitid of the current device. */
Eric Biederman0ac6b412003-09-02 17:16:48 +0000350 flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000351
Uwe Hermanne4870472010-11-04 23:23:47 +0000352 /*
Timothy Pearsond0c1dd02015-01-23 20:22:56 -0600353 * If the device has a unitid set and is at devfn 0 we are
Uwe Hermanne4870472010-11-04 23:23:47 +0000354 * done. This can happen with shadow hypertransport devices,
355 * or if we have reached the bottom of a HT device chain.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000356 */
Uwe Hermanne4870472010-11-04 23:23:47 +0000357 if (flags & 0x1f)
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000358 break;
Yinghai Luecad5df2007-05-21 18:11:17 +0000359
Uwe Hermanne4870472010-11-04 23:23:47 +0000360 flags &= ~0x1f; /* Mask out base Unit ID. */
361
362 count = (flags >> 5) & 0x1f; /* Het unit count. */
363
Stefan Reinauer08670622009-06-30 15:17:49 +0000364#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
Uwe Hermanne4870472010-11-04 23:23:47 +0000365 if (offset_unitid) {
366 /* max_devfn will be (0x17<<3)|7 or (0x1f<<3)|7. */
367 if (next_unitid > (max_devfn >> 3)) {
368 if (!end_used) {
369 next_unitid =
370 CONFIG_HT_CHAIN_END_UNITID_BASE;
Yinghai Lu18c70d72007-09-14 14:58:33 +0000371 end_used = 1;
372 } else {
Stefan Reinauer0dff6e32007-10-23 22:17:45 +0000373 goto end_of_chain;
Yinghai Lu18c70d72007-09-14 14:58:33 +0000374 }
Yinghai Luecad5df2007-05-21 18:11:17 +0000375 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000376 }
Yinghai Luecad5df2007-05-21 18:11:17 +0000377#endif
378
Uwe Hermanne4870472010-11-04 23:23:47 +0000379 flags |= next_unitid & 0x1f;
380 pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags);
Eric Biederman0ac6b412003-09-02 17:16:48 +0000381
Uwe Hermanne4870472010-11-04 23:23:47 +0000382 /* Update the unitid in the device structure. */
Eric Biederman0ac6b412003-09-02 17:16:48 +0000383 static_count = 1;
Uwe Hermanne4870472010-11-04 23:23:47 +0000384 for (func = dev; func; func = func->sibling) {
Stefan Reinauer2b34db82009-02-28 20:10:20 +0000385 func->path.pci.devfn += (next_unitid << 3);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000386 static_count = (func->path.pci.devfn >> 3)
Uwe Hermanne4870472010-11-04 23:23:47 +0000387 - (dev->path.pci.devfn >> 3) + 1;
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000388 last_func = func;
Eric Biederman0ac6b412003-09-02 17:16:48 +0000389 }
Eric Biederman0ac6b412003-09-02 17:16:48 +0000390
Uwe Hermanne4870472010-11-04 23:23:47 +0000391 /* Compute the number of unitids consumed. */
392 printk(BIOS_SPEW, "%s count: %04x static_count: %04x\n",
393 dev_path(dev), count, static_count);
394 if (count < static_count)
395 count = static_count;
396
397 /* Update the unitid of the next device. */
Yinghai Lu18c70d72007-09-14 14:58:33 +0000398 ht_unitid_base[ht_dev_num] = next_unitid;
Stefan Reinauerbbdd8f42005-12-04 21:52:58 +0000399 ht_dev_num++;
Yinghai Luecad5df2007-05-21 18:11:17 +0000400
Stefan Reinauer08670622009-06-30 15:17:49 +0000401#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
Yinghai Lu18c70d72007-09-14 14:58:33 +0000402 if (offset_unitid) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000403 real_last_pos = pos;
Yinghai Lu18c70d72007-09-14 14:58:33 +0000404 real_last_unitid = next_unitid;
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000405 real_last_dev = dev;
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000406 }
407#endif
Uwe Hermanne4870472010-11-04 23:23:47 +0000408 next_unitid += count;
409 if (next_unitid > max_unitid)
Yinghai Lu18c70d72007-09-14 14:58:33 +0000410 max_unitid = next_unitid;
Eric Biederman0ac6b412003-09-02 17:16:48 +0000411
Martin Roth63373ed2013-07-08 16:24:19 -0600412 /* Setup the hypertransport link. */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000413 bus->reset_needed |= ht_setup_link(&prev, dev, pos);
Eric Biederman0ac6b412003-09-02 17:16:48 +0000414
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000415 printk(BIOS_DEBUG, "%s [%04x/%04x] %s next_unitid: %04x\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000416 dev_path(dev), dev->vendor, dev->device,
417 (dev->enabled? "enabled" : "disabled"), next_unitid);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000418
Yinghai Lu18c70d72007-09-14 14:58:33 +0000419 } while (last_unitid != next_unitid);
Uwe Hermanne4870472010-11-04 23:23:47 +0000420
421end_of_chain:
422
Stefan Reinauer08670622009-06-30 15:17:49 +0000423#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
Uwe Hermanne4870472010-11-04 23:23:47 +0000424 if (offset_unitid && (ht_dev_num > 1)
425 && (real_last_unitid != CONFIG_HT_CHAIN_END_UNITID_BASE)
426 && !end_used) {
427 u16 flags;
428 flags = pci_read_config16(real_last_dev,
429 real_last_pos + PCI_CAP_FLAGS);
430 flags &= ~0x1f;
431 flags |= CONFIG_HT_CHAIN_END_UNITID_BASE & 0x1f;
432 pci_write_config16(real_last_dev,
433 real_last_pos + PCI_CAP_FLAGS, flags);
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000434
Uwe Hermanne4870472010-11-04 23:23:47 +0000435 for (func = real_last_dev; func; func = func->sibling) {
436 func->path.pci.devfn -= ((real_last_unitid
437 - CONFIG_HT_CHAIN_END_UNITID_BASE) << 3);
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000438 last_func = func;
Uwe Hermanne4870472010-11-04 23:23:47 +0000439 }
Yinghai Luecad5df2007-05-21 18:11:17 +0000440
Uwe Hermanne4870472010-11-04 23:23:47 +0000441 /* Update last one. */
442 ht_unitid_base[ht_dev_num-1] = CONFIG_HT_CHAIN_END_UNITID_BASE;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000443
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000444 printk(BIOS_DEBUG, " unitid: %04x --> %04x\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000445 real_last_unitid, CONFIG_HT_CHAIN_END_UNITID_BASE);
446 }
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000447#endif
Yinghai Lu18c70d72007-09-14 14:58:33 +0000448 next_unitid = max_unitid;
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000449
Uwe Hermanne4870472010-11-04 23:23:47 +0000450 if (next_unitid > 0x20)
Yinghai Lu18c70d72007-09-14 14:58:33 +0000451 next_unitid = 0x20;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000452
Uwe Hermanne4870472010-11-04 23:23:47 +0000453 if ((bus->secondary == 0) && (next_unitid > 0x18))
454 next_unitid = 0x18; /* Avoid K8 on bus 0. */
455
456 /*
457 * Die if any leftover static devices are are found. There's probably
458 * a problem in devicetree.cb.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000459 */
Uwe Hermanne4870472010-11-04 23:23:47 +0000460 if (old_devices) {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000461 device_t left;
Uwe Hermanne4870472010-11-04 23:23:47 +0000462 for (left = old_devices; left; left = left->sibling)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000463 printk(BIOS_DEBUG, "%s\n", dev_path(left));
Uwe Hermanne4870472010-11-04 23:23:47 +0000464
465 printk(BIOS_ERR, "HT: Leftover static devices. "
466 "Check your devicetree.cb\n");
467
468 /*
469 * Put back the leftover static device, and let pci_scan_bus()
470 * disable it.
471 */
472 if (last_func && !last_func->sibling)
Stefan Reinauer14e22772010-04-27 06:56:47 +0000473 last_func->sibling = old_devices;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000474 }
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000475
Kyösti Mälkkib39714e2015-03-12 16:16:59 +0200476 return next_unitid;
Eric Biederman0ac6b412003-09-02 17:16:48 +0000477}
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000478
Kyösti Mälkkied7bc2c2015-02-22 08:27:13 +0200479unsigned int hypertransport_scan_chain(struct bus *bus)
480{
481 int i;
482 unsigned int max_devfn;
483 u32 ht_unitid_base[4];
484
485 for (i = 0; i < 4; i++)
486 ht_unitid_base[i] = 0x20;
487
488 if (bus->secondary == 0)
489 max_devfn = (CONFIG_CDB << 3) - 1;
490 else
491 max_devfn = (0x20 << 3) - 1;
492
493 unsigned int next_unitid = do_hypertransport_scan_chain(bus, 0, max_devfn,
494 ht_unitid_base, offset_unit_id(bus->secondary == 0));
495
496 bus->hcdn_reg = 0;
497 for (i = 0; i < 4; i++)
498 bus->hcdn_reg |= (ht_unitid_base[i] & 0xff) << (i*8);
499
500 return next_unitid;
501}
502
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000503/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000504 * Scan a PCI bridge and the buses behind the bridge.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000505 *
506 * Determine the existence of buses behind the bridge. Set up the bridge
507 * according to the result of the scan.
508 *
509 * This function is the default scan_bus() method for PCI bridge devices.
510 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000511 * @param bus TODO
512 * @param min_devfn TODO
513 * @param max_devfn TODO
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000514 */
Kyösti Mälkkide271a82015-03-18 13:09:47 +0200515static void hypertransport_scan_chain_x(struct bus *bus,
516 unsigned int min_devfn, unsigned int max_devfn)
Yinghai Lud4b278c2006-10-04 20:46:15 +0000517{
Uwe Hermanne4870472010-11-04 23:23:47 +0000518 unsigned int ht_unitid_base[4];
519 unsigned int offset_unitid = 1;
Kyösti Mälkkib39714e2015-03-12 16:16:59 +0200520
Kyösti Mälkkied7bc2c2015-02-22 08:27:13 +0200521 unsigned int next_unitid = do_hypertransport_scan_chain(bus, min_devfn, max_devfn,
Uwe Hermanne4870472010-11-04 23:23:47 +0000522 ht_unitid_base, offset_unitid);
Kyösti Mälkkib39714e2015-03-12 16:16:59 +0200523
524 /* Now that nothing is overlapping it is safe to scan the children. */
Kyösti Mälkkide271a82015-03-18 13:09:47 +0200525 pci_scan_bus(bus, 0x00, ((next_unitid - 1) << 3) | 7);
Yinghai Lud4b278c2006-10-04 20:46:15 +0000526}
527
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200528void ht_scan_bridge(struct device *dev)
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000529{
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200530 do_pci_scan_bridge(dev, hypertransport_scan_chain_x);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000531}
532
Kyösti Mälkki0a3d4e42015-02-23 00:34:26 +0200533bool ht_is_non_coherent_link(struct bus *link)
534{
535 u32 link_type;
536 do {
537 link_type = pci_read_config32(link->dev, link->cap + 0x18);
538 } while (link_type & ConnectionPending);
539
540 if (!(link_type & LinkConnected))
541 return false;
542
543 do {
544 link_type = pci_read_config32(link->dev, link->cap + 0x18);
545 } while (!(link_type & InitComplete));
546
547 return !!(link_type & NonCoherent);
548}
549
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000550/** Default device operations for hypertransport bridges */
551static struct pci_operations ht_bus_ops_pci = {
552 .set_subsystem = 0,
553};
554
555struct device_operations default_ht_ops_bus = {
556 .read_resources = pci_bus_read_resources,
557 .set_resources = pci_dev_set_resources,
558 .enable_resources = pci_bus_enable_resources,
Uwe Hermanne4870472010-11-04 23:23:47 +0000559 .init = 0,
560 .scan_bus = ht_scan_bridge,
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000561 .enable = 0,
562 .reset_bus = pci_bus_reset,
563 .ops_pci = &ht_bus_ops_pci,
564};