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.
21
#include <ccan/str/str.h>
22
#include <interrupts.h>
26
static struct dt_node *fsp_create_node(const void *spss, int i,
27
struct dt_node *parent)
29
const struct spss_sp_impl *sp_impl;
33
/* Find an check the SP Implementation structure */
34
sp_impl = HDIF_get_idata(spss, SPSS_IDATA_SP_IMPL, NULL);
35
if (!CHECK_SPPTR(sp_impl)) {
36
prerror("FSP #%d: SPSS/SP_Implementation not found !\n", i);
40
prlog(PR_INFO, "FSP #%d: FSP HW version %d, SW version %d,"
42
be16_to_cpu(sp_impl->hw_version),
43
be16_to_cpu(sp_impl->sw_version),
44
sp_impl->chip_version >> 4, sp_impl->chip_version & 0xf);
45
mask = SPSS_SP_IMPL_FLAGS_INSTALLED | SPSS_SP_IMPL_FLAGS_FUNCTIONAL;
46
if ((be16_to_cpu(sp_impl->func_flags) & mask) != mask) {
47
prerror("FSP #%d: FSP not installed or not functional\n", i);
51
node = dt_new_addr(parent, "fsp", i);
53
dt_add_property_cells(node, "reg", i);
55
if (be16_to_cpu(sp_impl->hw_version) == 1) {
56
dt_add_property_strings(node, "compatible", "ibm,fsp",
58
/* Offset into the FSP MMIO space where the mailbox
60
/* seen in the FSP1 spec */
61
dt_add_property_cells(node, "reg-offset", 0xb0016000);
62
} else if (be16_to_cpu(sp_impl->hw_version) == 2) {
63
dt_add_property_strings(node, "compatible", "ibm,fsp",
65
dt_add_property_cells(node, "reg-offset", 0xb0011000);
67
dt_add_property_cells(node, "hw-version", be16_to_cpu(sp_impl->hw_version));
68
dt_add_property_cells(node, "sw-version", be16_to_cpu(sp_impl->sw_version));
70
if (be16_to_cpu(sp_impl->func_flags) & SPSS_SP_IMPL_FLAGS_PRIMARY)
71
dt_add_property(node, "primary", NULL, 0);
76
static uint32_t fsp_create_link(const struct spss_iopath *iopath, int index,
85
switch(be16_to_cpu(iopath->psi.link_status)) {
86
case SPSS_IO_PATH_PSI_LINK_BAD_FRU:
89
case SPSS_IO_PATH_PSI_LINK_CURRENT:
91
current = working = true;
93
case SPSS_IO_PATH_PSI_LINK_BACKUP:
100
prlog(PR_DEBUG, "FSP #%d: IO PATH %d is %s PSI Link, GXHB at %llx\n",
101
fsp_index, index, ststr, (long long)be64_to_cpu(iopath->psi.gxhb_base));
103
chip_id = pcid_to_chip_id(be32_to_cpu(iopath->psi.proc_chip_id));
104
node = dt_find_compatible_node_on_chip(dt_root, NULL, "ibm,psihb-x",
107
prerror("FSP #%d: Can't find psihb node for link %d\n",
111
dt_add_property(node, "boot-link", NULL, 0);
112
dt_add_property_strings(node, "status", working ? "ok" : "bad");
118
static void fsp_create_links(const void *spss, int index,
119
struct dt_node *fsp_node)
121
uint32_t *links = NULL;
122
unsigned int i, lp, lcount = 0;
125
count = HDIF_get_iarray_size(spss, SPSS_IDATA_SP_IOPATH);
127
prerror("FSP #%d: Can't find IO PATH array size !\n", index);
130
prlog(PR_DEBUG, "FSP #%d: Found %d IO PATH\n", index, count);
132
/* Iterate all links */
133
for (i = 0; i < count; i++) {
134
const struct spss_iopath *iopath;
135
unsigned int iopath_sz;
138
iopath = HDIF_get_iarray_item(spss, SPSS_IDATA_SP_IOPATH,
140
if (!CHECK_SPPTR(iopath)) {
141
prerror("FSP #%d: Can't find IO PATH %d\n", index, i);
144
if (be16_to_cpu(iopath->iopath_type) != SPSS_IOPATH_TYPE_PSI) {
145
prerror("FSP #%d: Unsupported IO PATH %d type 0x%04x\n",
146
index, i, iopath->iopath_type);
150
chip = fsp_create_link(iopath, i, index);
152
links = realloc(links, 4 * lcount);
156
dt_add_property(fsp_node, "ibm,psi-links", links, lcount * 4);
163
const void *base_spss, *spss;
164
struct dt_node *fsp_root, *fsp_node;
168
* Note on DT representation of the PSI links and FSPs:
170
* We create a XSCOM node for each PSI host bridge(one per chip),
172
* This is done in spira.c
174
* We do not create the /psi MMIO variant at this stage, it will
175
* be added by the psi driver in skiboot.
177
* We do not put the FSP(s) as children of these. Instead, we create
178
* a top-level /fsps node with the FSPs as children.
180
* Each FSP then has a "links" property which is an array of chip IDs
183
/* Find SPSS in SPIRA */
184
base_spss = get_hdif(&spira.ntuples.sp_subsys, SPSS_HDIF_SIG);
186
prlog(PR_WARNING, "FSP: No SPSS in SPIRA !\n");
190
fsp_root = dt_new(dt_root, "fsps");
192
dt_add_property_cells(fsp_root, "#address-cells", 1);
193
dt_add_property_cells(fsp_root, "#size-cells", 0);
195
/* Iterate FSPs in SPIRA */
196
for_each_ntuple_idx(&spira.ntuples.sp_subsys, spss, i, SPSS_HDIF_SIG) {
197
fsp_node = fsp_create_node(spss, i, fsp_root);
199
fsp_create_links(spss, i, fsp_node);