1
/* Copyright 2013-2014 IBM Corp.
3
* Licensed under the Apache License, Version 2.0 (the "License");
4
* you may not use this file except in compliance with the License.
5
* You may obtain a copy of the License at
7
* http://www.apache.org/licenses/LICENSE-2.0
9
* Unless required by applicable law or agreed to in writing, software
10
* distributed under the License is distributed on an "AS IS" BASIS,
11
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
16
#define pr_fmt(fmt) "LXVPD: " fmt
28
* Currently, the lxvpd PCI slot struct is shared by multiple
29
* platforms (Apollo and Firenze), but each slot still has
30
* platform specific features. In order for unified data structs,
31
* "struct lxvpd_slot" is expected to be embedded in platform
32
* PCI slot struct. "entry_size" indicates the size of platform
33
* specific PCI slot instance.
35
struct lxvpd_pci_slot_data {
37
int32_t entry_size; /* Size of platform PCI slot */
38
void *slots; /* Data of platform PCI slots */
41
static bool lxvpd_supported_slot(struct phb *phb, struct pci_device *pd)
43
/* PHB should always be valid */
47
/* We expect platform slot for root complex */
51
/* We support the root complex at the top level */
52
if (pd->dev_type == PCIE_TYPE_ROOT_PORT && !pd->parent)
55
/* We support an upstream switch port below the root complex */
56
if (pd->dev_type == PCIE_TYPE_SWITCH_UPPORT &&
57
pd->parent && pd->parent->dev_type == PCIE_TYPE_ROOT_PORT &&
61
/* We support a downstream switch port below an upstream port
62
* below the root complex
64
if (pd->dev_type == PCIE_TYPE_SWITCH_DNPORT &&
65
pd->parent && pd->parent->dev_type == PCIE_TYPE_SWITCH_UPPORT &&
67
pd->parent->parent->dev_type == PCIE_TYPE_ROOT_PORT &&
68
!pd->parent->parent->parent)
71
/* Anything else, bail */
75
void *lxvpd_get_slot(struct pci_slot *slot)
77
struct phb *phb = slot->phb;
78
struct pci_device *pd = slot->pd;
79
struct lxvpd_pci_slot_data *sdata = phb->platform_data;
80
struct lxvpd_pci_slot *s = NULL;
81
uint8_t slot_num = pd ? ((pd->bdfn >> 3) & 0x1f) : 0xff;
82
bool is_phb = (pd && pd->parent) ? false : true;
85
/* Check if we have slot info */
87
prlog(PR_DEBUG, "PHB%04x not have VPD data\n",
92
/* Platform slot attached ? */
95
prlog(PR_DEBUG, "Slot %016llx had platform data [%s]\n",
101
* This code only handles PHBs and PCIe switches at the
102
* top level. We do not handle any other switch nor any
103
* other type of PCI/PCI-X bridge. Generally, we have
104
* more strict rules to support slot than PCI core.
106
if (!lxvpd_supported_slot(phb, pd)) {
107
prlog(PR_DEBUG, "Slot %016llx not supported\n",
112
/* Iterate the platform slot array */
113
for (index = 0; index < sdata->num_slots; index++) {
114
s = sdata->slots + (index * sdata->entry_size);
116
/* Match PHB with switch_id == 0 */
117
if (is_phb && s->switch_id == 0) {
120
prlog(PR_DEBUG, "Found [%s] for PHB slot %016llx\n",
126
/* Match switch port with switch_id != 0 */
127
if (!is_phb && s->switch_id != 0 && s->dev_id == slot_num) {
130
prlog(PR_DEBUG, "Found [%s] for slot %016llx\n",
137
prlog(PR_DEBUG, "No data found for %sslot %016llx\n",
138
is_phb ? "PHB " : " ", slot->id);
142
void lxvpd_extract_info(struct pci_slot *slot, struct lxvpd_pci_slot *s)
144
slot->pluggable = s->pluggable ? 1 : 0;
145
slot->power_ctl = s->power_ctl ? 1 : 0;
146
slot->power_led_ctl = s->pwr_led_ctl;
147
slot->attn_led_ctl = s->attn_led_ctl;
148
slot->connector_type = s->connector_type;
149
slot->card_desc = s->card_desc;
150
slot->card_mech = s->card_mech;
151
slot->wired_lanes = s->wired_lanes;
154
static struct lxvpd_pci_slot_data *lxvpd_alloc_slots(struct phb *phb,
158
struct lxvpd_pci_slot_data *sdata;
160
sdata = zalloc(sizeof(struct lxvpd_pci_slot_data) + count * slot_size);
162
sdata->num_slots = count;
163
sdata->entry_size = slot_size;
164
sdata->slots = sdata + 1;
165
phb->platform_data = sdata;
170
static void lxvpd_format_label(char *dst, const char *src, size_t len)
174
memcpy(dst, src, len);
176
/* Remove blank suffix */
177
for (i = strlen(dst) - 1; i >= 0; i--) {
185
static void lxvpd_parse_1004_map(struct phb *phb,
190
struct lxvpd_pci_slot_data *sdata;
191
struct lxvpd_pci_slot *s;
192
const struct pci_slot_entry_1004 *entry;
193
uint8_t num_slots, slot;
195
num_slots = (size / sizeof(struct pci_slot_entry_1004));
196
sdata = lxvpd_alloc_slots(phb, num_slots, slot_size);
198
/* Iterate through the entries in the keyword */
199
entry = (const struct pci_slot_entry_1004 *)sm;
200
for (slot = 0; slot < num_slots; slot++, entry++) {
201
s = sdata->slots + slot * sdata->entry_size;
203
/* Figure out PCI slot info */
204
lxvpd_format_label(s->label, entry->label, 3);
205
s->slot_index = entry->slot_index;
206
s->switch_id = entry->pba >> 4;
207
s->vswitch_id = entry->pba & 0xf;
208
s->dev_id = entry->sba;
209
s->pluggable = ((entry->p0.byte & 0x20) == 0);
210
s->power_ctl = !!(entry->p0.byte & 0x40);
211
s->bus_clock = entry->p2.bus_clock - 4;
212
s->connector_type = entry->p2.connector_type - 5;
213
s->card_desc = entry->p3.byte >> 6;
214
if (entry->p3.byte < 0xc0)
216
s->card_mech = (entry->p3.byte >> 4) & 0x3;
217
s->pwr_led_ctl = (entry->p3.byte & 0xf) >> 2;
218
s->attn_led_ctl = entry->p3.byte & 0x3;
220
switch(entry->p1.wired_lanes) {
221
case 1: s->wired_lanes = PCI_SLOT_WIRED_LANES_PCIX_32; break;
222
case 2: /* fall through */
223
case 3: s->wired_lanes = PCI_SLOT_WIRED_LANES_PCIX_64; break;
224
case 4: s->wired_lanes = PCI_SLOT_WIRED_LANES_PCIE_X1; break;
225
case 5: s->wired_lanes = PCI_SLOT_WIRED_LANES_PCIE_X4; break;
226
case 6: s->wired_lanes = PCI_SLOT_WIRED_LANES_PCIE_X8; break;
227
case 7: s->wired_lanes = PCI_SLOT_WIRED_LANES_PCIE_X16; break;
229
s->wired_lanes = PCI_SLOT_WIRED_LANES_UNKNOWN;
232
prlog(PR_DEBUG, "1004 Platform data [%s] %02x %02x on PHB%04x\n",
233
s->label, s->switch_id, s->dev_id, phb->opal_id);
237
static void lxvpd_parse_1005_map(struct phb *phb,
242
struct lxvpd_pci_slot_data *sdata;
243
struct lxvpd_pci_slot *s;
244
const struct pci_slot_entry_1005 *entry;
245
uint8_t num_slots, slot;
247
num_slots = (size / sizeof(struct pci_slot_entry_1005));
248
sdata = lxvpd_alloc_slots(phb, num_slots, slot_size);
250
/* Iterate through the entries in the keyword */
251
entry = (const struct pci_slot_entry_1005 *)sm;
252
for (slot = 0; slot < num_slots; slot++, entry++) {
253
s = sdata->slots + slot * sdata->entry_size;
255
/* Put slot info into pci device structure */
256
lxvpd_format_label(s->label, entry->label, 8);
257
s->slot_index = entry->slot_index;
258
s->switch_id = entry->pba >> 4;
259
s->vswitch_id = entry->pba & 0xf;
260
s->dev_id = entry->switch_device_id;
261
s->pluggable = (entry->p0.pluggable == 0);
262
s->power_ctl = entry->p0.power_ctl;
263
s->bus_clock = entry->p2.bus_clock;
264
s->connector_type = entry->p2.connector_type;
265
s->card_desc = entry->p3.byte >> 6;
266
s->card_mech = (entry->p3.byte >> 4) & 0x3;
267
s->pwr_led_ctl = (entry->p3.byte & 0xf) >> 2;
268
s->attn_led_ctl = entry->p3.byte & 0x3;
269
s->wired_lanes = entry->p1.wired_lanes;
270
if (s->wired_lanes > PCI_SLOT_WIRED_LANES_PCIE_X32)
271
s->wired_lanes = PCI_SLOT_WIRED_LANES_UNKNOWN;
273
prlog(PR_DEBUG, "1005 Platform data [%s] %02x %02x on PHB%04x\n",
274
s->label, s->switch_id, s->dev_id, phb->opal_id);
278
void lxvpd_process_slot_entries(struct phb *phb,
279
struct dt_node *node,
285
const uint8_t *pr_rec, *pr_end, *sm;
286
size_t lxvpd_size, pr_size;
287
const uint16_t *mf = NULL;
288
char record[5] = "PR00";
289
uint8_t mf_sz, sm_sz;
292
record[2] += chip_id;
296
/* Get LX VPD pointer */
297
lxvpd = dt_prop_get_def_size(node, "ibm,io-vpd", NULL, &lxvpd_size);
299
prlog(PR_WARNING, "No data found for PHB%04x %s\n",
300
phb->opal_id, record);
304
pr_rec = vpd_find_record(lxvpd, lxvpd_size, record, &pr_size);
306
prlog(PR_WARNING, "Record %s not found on PHB%04x\n",
307
record, phb->opal_id);
311
/* As long as there's still something in the PRxy record */
312
prlog(PR_DEBUG, "PHB%04x record %s has %ld bytes\n",
313
phb->opal_id, record, pr_size);
314
pr_end = pr_rec + pr_size;
315
while (pr_rec < pr_end) {
316
pr_size = pr_end - pr_rec;
318
/* Find the next MF keyword */
319
mf = vpd_find_keyword(pr_rec, pr_size, "MF", &mf_sz);
320
/* And the corresponding SM */
321
sm = vpd_find_keyword(pr_rec, pr_size, "SM", &sm_sz);
324
prlog(PR_WARNING, "Slot Map keyword %s not found\n",
329
prlog(PR_DEBUG, "Found 0x%04x map...\n", *mf);
332
lxvpd_parse_1004_map(phb, sm + 1, sm_sz - 1, slot_size);
336
lxvpd_parse_1005_map(phb, sm + 1, sm_sz - 1, slot_size);
339
/* Add support for 0x1006 maps ... */
346
void lxvpd_add_slot_properties(struct pci_slot *slot,
349
struct phb *phb = slot->phb;
350
struct lxvpd_pci_slot *s = slot->data;
351
char loc_code[LOC_CODE_SIZE];
352
size_t base_loc_code_len, slot_label_len;
354
/* Check if we have platform specific slot */
358
/* Check PHB base location code */
359
if (!phb->base_loc_code)
362
/* Check location length is valid */
363
base_loc_code_len = strlen(phb->base_loc_code);
364
slot_label_len = strlen(s->label);
365
if ((base_loc_code_len + slot_label_len + 1) >= LOC_CODE_SIZE)
369
strcpy(loc_code, phb->base_loc_code);
370
strcat(loc_code, "-");
371
strcat(loc_code, s->label);
372
dt_add_property(np, "ibm,slot-location-code",
373
loc_code, strlen(loc_code) + 1);
374
dt_add_property_string(np, "ibm,slot-label",