aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-07-02 15:36:20 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-07-02 15:36:20 +1000
commit1d880992fd8c8457a2d990ac6622cfd58fb1b261 (patch)
treec4c843b12e96b5612c315db5a23c5da1a900618c /include
downloadskiboot-1d880992fd8c8457a2d990ac6622cfd58fb1b261.zip
skiboot-1d880992fd8c8457a2d990ac6622cfd58fb1b261.tar.gz
skiboot-1d880992fd8c8457a2d990ac6622cfd58fb1b261.tar.bz2
Initial commit of Open Source release
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'include')
-rw-r--r--include/affinity.h34
-rw-r--r--include/asm-utils.h45
-rw-r--r--include/ast.h78
-rw-r--r--include/bitutils.h50
-rw-r--r--include/capp.h62
-rw-r--r--include/cec.h51
-rw-r--r--include/centaur.h24
-rw-r--r--include/chip.h151
-rw-r--r--include/chiptod.h28
-rw-r--r--include/codeupdate.h236
-rw-r--r--include/compiler.h50
-rw-r--r--include/config.h93
-rw-r--r--include/console.h68
-rw-r--r--include/cpu.h207
-rw-r--r--include/device.h233
-rw-r--r--include/device_tree.h35
-rw-r--r--include/ec/config.h82
-rw-r--r--include/ec/gpio.h53
-rw-r--r--include/elf.h135
-rw-r--r--include/fsi-master.h36
-rw-r--r--include/fsp-elog.h325
-rw-r--r--include/fsp-leds.h135
-rw-r--r--include/fsp-mdst-table.h37
-rw-r--r--include/fsp-sysparam.h57
-rw-r--r--include/fsp.h755
-rw-r--r--include/gx.h59
-rw-r--r--include/hostservices.h36
-rw-r--r--include/interrupts.h254
-rw-r--r--include/io.h175
-rw-r--r--include/lock.h83
-rw-r--r--include/lpc.h95
-rw-r--r--include/mem-map.h114
-rw-r--r--include/mem_region-malloc.h41
-rw-r--r--include/mem_region.h69
-rw-r--r--include/memory.h23
-rw-r--r--include/nx.h22
-rw-r--r--include/op-panel.h67
-rw-r--r--include/opal-internal.h234
-rw-r--r--include/opal-msg.h36
-rw-r--r--include/opal.h912
-rw-r--r--include/p5ioc2-regs.h251
-rw-r--r--include/p5ioc2.h184
-rw-r--r--include/p7ioc-regs.h472
-rw-r--r--include/p7ioc.h431
-rw-r--r--include/pci-cfg.h524
-rw-r--r--include/pci.h504
-rw-r--r--include/phb3-regs.h436
-rw-r--r--include/phb3.h355
-rw-r--r--include/platform.h122
-rw-r--r--include/processor.h318
-rw-r--r--include/psi.h239
-rw-r--r--include/sfc-ctrl.h24
-rw-r--r--include/skiboot.h202
-rw-r--r--include/spcn.h93
-rw-r--r--include/stack.h92
-rw-r--r--include/timebase.h91
-rw-r--r--include/trace.h46
-rw-r--r--include/trace_types.h132
-rw-r--r--include/types.h27
-rw-r--r--include/vpd.h45
-rw-r--r--include/xscom.h171
61 files changed, 10039 insertions, 0 deletions
diff --git a/include/affinity.h b/include/affinity.h
new file mode 100644
index 0000000..eba26db
--- /dev/null
+++ b/include/affinity.h
@@ -0,0 +1,34 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ *
+ * All functions in charge of generating the associativity/affinity
+ * properties in the device-tree
+ */
+
+#ifndef __AFFINITY_H
+#define __AFFINITY_H
+
+struct dt_node;
+struct cpu_thread;
+
+extern void add_associativity_ref_point(void);
+
+extern void add_chip_dev_associativity(struct dt_node *dev);
+extern void add_core_associativity(struct cpu_thread *cpu);
+
+#endif /* __AFFINITY_H */
diff --git a/include/asm-utils.h b/include/asm-utils.h
new file mode 100644
index 0000000..503f2cc
--- /dev/null
+++ b/include/asm-utils.h
@@ -0,0 +1,45 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ASM_UTILS_H
+#define __ASM_UTILS_H
+
+/*
+ * Do NOT use the immediate load helpers with symbols
+ * only with constants. Symbols will _not_ be resolved
+ * by the linker since we are building -pie, and will
+ * instead generate relocs of a type our little built-in
+ * relocator can't handle
+ */
+
+/* Load an immediate 64-bit value into a register */
+#define LOAD_IMM64(r, e) \
+ lis r,(e)@highest; \
+ ori r,r,(e)@higher; \
+ rldicr r,r, 32, 31; \
+ oris r,r, (e)@h; \
+ ori r,r, (e)@l;
+
+/* Load an immediate 32-bit value into a register */
+#define LOAD_IMM32(r, e) \
+ lis r,(e)@h; \
+ ori r,r,(e)@l;
+
+/* Load an address via the TOC */
+#define LOAD_ADDR_FROM_TOC(r, e) ld r,e@got(%r2)
+
+
+#endif /* __ASM_UTILS_H */
diff --git a/include/ast.h b/include/ast.h
new file mode 100644
index 0000000..17ee17e
--- /dev/null
+++ b/include/ast.h
@@ -0,0 +1,78 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __AST_H
+#define __AST_H
+
+/*
+ * AHB bus registers
+ */
+
+/* SPI Flash controller #1 (BMC) */
+#define BMC_SPI_FCTL_BASE 0x1E620000
+#define BMC_SPI_FCTL_CTRL (BMC_SPI_FCTL_BASE + 0x10)
+#define BMC_FLASH_BASE 0x20000000
+
+/* SPI Flash controller #2 (PNOR) */
+#define PNOR_SPI_FCTL_BASE 0x1E630000
+#define PNOR_SPI_FCTL_CONF (PNOR_SPI_FCTL_BASE + 0x00)
+#define PNOR_SPI_FCTL_CTRL (PNOR_SPI_FCTL_BASE + 0x04)
+#define PNOR_FLASH_BASE 0x30000000
+
+/* LPC registers */
+#define LPC_BASE 0x1e789000
+#define LPC_HICR6 (LPC_BASE + 0x80)
+#define LPC_HICR7 (LPC_BASE + 0x88)
+#define LPC_HICR8 (LPC_BASE + 0x8c)
+
+/*
+ * AHB Accessors
+ */
+#ifndef __SKIBOOT__
+#include "io.h"
+#else
+
+/*
+ * Register accessors, return byteswapped values
+ * (IE. LE registers)
+ */
+void ast_ahb_writel(uint32_t val, uint32_t reg);
+uint32_t ast_ahb_readl(uint32_t reg);
+
+/*
+ * copy to/from accessors. Cannot cross IDSEL boundaries (256M)
+ */
+int ast_copy_to_ahb(uint32_t reg, const void *src, uint32_t len);
+int ast_copy_from_ahb(void *dst, uint32_t reg, uint32_t len);
+
+void ast_io_init(void);
+
+/* UART init */
+void ast_setup_uart1(uint16_t io_base, uint8_t irq);
+
+#endif /* __SKIBOOT__ */
+
+/*
+ * SPI Flash controllers
+ */
+#define AST_SF_TYPE_PNOR 0
+#define AST_SF_TYPE_BMC 1
+
+struct spi_flash_ctrl;
+int ast_sf_open(uint8_t type, struct spi_flash_ctrl **ctrl);
+void ast_sf_close(struct spi_flash_ctrl *ctrl);
+
+
+#endif /* __AST_H */
diff --git a/include/bitutils.h b/include/bitutils.h
new file mode 100644
index 0000000..7e5b6eb
--- /dev/null
+++ b/include/bitutils.h
@@ -0,0 +1,50 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BITUTILS_H
+#define __BITUTILS_H
+
+/* PPC bit number conversion */
+#ifdef __ASSEMBLY__
+#define PPC_BIT(bit) (0x8000000000000000 >> (bit))
+#define PPC_BIT32(bit) (0x80000000 >> (bit))
+#define PPC_BIT8(bit) (0x80 >> (bit))
+#else
+#define PPC_BIT(bit) (0x8000000000000000UL >> (bit))
+#define PPC_BIT32(bit) (0x80000000UL >> (bit))
+#define PPC_BIT8(bit) (0x80UL >> (bit))
+#endif
+#define PPC_BITMASK(bs,be) ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
+#define PPC_BITMASK32(bs,be) ((PPC_BIT32(bs) - PPC_BIT32(be))|PPC_BIT32(bs))
+#define PPC_BITLSHIFT(be) (63 - (be))
+#define PPC_BITLSHIFT32(be) (31 - (be))
+
+/*
+ * PPC bitmask field manipulation
+ */
+
+/* Extract field fname from val */
+#define GETFIELD(fname, val) \
+ (((val) & fname##_MASK) >> fname##_LSH)
+
+/* Set field fname of oval to fval
+ * NOTE: oval isn't modified, the combined result is returned
+ */
+#define SETFIELD(fname, oval, fval) \
+ (((oval) & ~fname##_MASK) | \
+ ((((typeof(oval))(fval)) << fname##_LSH) & fname##_MASK))
+
+#endif /* __BITUTILS_H */
diff --git a/include/capp.h b/include/capp.h
new file mode 100644
index 0000000..ddf280d
--- /dev/null
+++ b/include/capp.h
@@ -0,0 +1,62 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+struct capp_ucode_lid_hdr {
+ uint64_t eyecatcher; /* 'CAPPULID' in ASCII */
+ uint64_t version;
+ uint64_t data_size; /* total size of all capp microcode data following header */
+ u8 reserved[40]; /* zeroed, pads to 64 byte boundary */
+};
+
+struct capp_ucode_data_hdr
+{
+ uint64_t eyecatcher; /* 'CAPPUCOD' in ASCII */
+ u8 version;
+ u8 reg;
+ u8 reserved[2];
+ uint32_t num_data_chunks; /* Number of 8-byte chunks of data that follow this header */
+};
+
+enum capp_reg {
+ apc_master_cresp = 0x1,
+ apc_master_uop_table = 0x2,
+ snp_ttype = 0x3,
+ snp_uop_table = 0x4,
+ apt_master_capi_ctrl = 0x5,
+ snoop_capi_cnfg = 0x6,
+ canned_presp_map0 = 0x7,
+ canned_presp_map1 = 0x8,
+ canned_presp_map2 = 0x9,
+ flush_sue_state_map = 0xA,
+ apc_master_powerbus_ctrl = 0xB
+};
+
+#define CAPP_SNP_ARRAY_ADDR_REG 0x2013028
+#define CAPP_APC_MASTER_ARRAY_ADDR_REG 0x201302A
+#define CAPP_SNP_ARRAY_WRITE_REG 0x2013801
+#define CAPP_APC_MASTER_ARRAY_WRITE_REG 0x2013802
+
+#define APC_MASTER_PB_CTRL 0x2013018
+#define APC_MASTER_CONFIG 0x2013019
+#define TRANSPORT_CONTROL 0x201301C
+#define CANNED_PRESP_MAP0 0x201301D
+#define CANNED_PRESP_MAP1 0x201301E
+#define CANNED_PRESP_MAP2 0x201301F
+#define CAPP_ERR_STATUS_CTRL 0x201300E
+#define FLUSH_SUE_STATE_MAP 0x201300F
+#define CAPP_EPOCH_TIMER_CTRL 0x201302C
+#define FLUSH_UOP_CONFIG1 0x2013803
+#define FLUSH_UOP_CONFIG2 0x2013804
+#define SNOOP_CAPI_CONFIG 0x201301A
diff --git a/include/cec.h b/include/cec.h
new file mode 100644
index 0000000..87cdc0e
--- /dev/null
+++ b/include/cec.h
@@ -0,0 +1,51 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CEC_H
+#define __CEC_H
+
+#include <stdint.h>
+
+/* This represent an IO Hub and contains the function pointers
+ * for the IO Hub related OPAL ops and other internal functions
+ */
+
+struct io_hub;
+
+struct io_hub_ops {
+ /* OPAL_PCI_SET_HUB_TCE_MEMORY (p5ioc2 only) */
+ int64_t (*set_tce_mem)(struct io_hub *hub, uint64_t address,
+ uint64_t size);
+
+ /* OPAL_PCI_GET_HUB_DIAG_DATA */
+ int64_t (*get_diag_data)(struct io_hub *hub, void *diag_buffer,
+ uint64_t diag_buffer_len);
+
+ /* Called on fast reset */
+ void (*reset)(struct io_hub *hub);
+};
+
+struct io_hub {
+ uint32_t hub_id;
+ const struct io_hub_ops *ops;
+};
+
+extern struct io_hub *cec_get_hub_by_id(uint32_t hub_id);
+
+extern void cec_reset(void);
+extern void cec_register(struct io_hub *hub);
+
+#endif /* __CEC_H */
diff --git a/include/centaur.h b/include/centaur.h
new file mode 100644
index 0000000..4a5e52c
--- /dev/null
+++ b/include/centaur.h
@@ -0,0 +1,24 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CENTAUR_H
+#define __CENTAUR_H
+
+extern int64_t centaur_xscom_read(uint32_t id, uint64_t pcb_addr, uint64_t *val);
+extern int64_t centaur_xscom_write(uint32_t id, uint64_t pcb_addr, uint64_t val);
+extern void centaur_init(void);
+
+#endif /* __CENTAUR_H */
diff --git a/include/chip.h b/include/chip.h
new file mode 100644
index 0000000..10623e6
--- /dev/null
+++ b/include/chip.h
@@ -0,0 +1,151 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CHIP_H
+#define __CHIP_H
+
+#include <stdint.h>
+#include <lock.h>
+
+/*
+ * Note on chip IDs:
+ *
+ * We carry a "chip_id" around, in the cpu_thread, but also as
+ * ibm,chip-id properties.
+ *
+ * This ID is the HW fabric ID of a chip based on the XSCOM numbering,
+ * also known as "GCID" (Global Chip ID).
+ *
+ * The format of this number is different between P7 and P8 and care must
+ * be taken when trying to convert between this chip ID and some other
+ * representation such as PIR values, interrupt-server numbers etc... :
+ *
+ * P7 GCID
+ * -------
+ *
+ * Global chip ID is a 6 bit number:
+ *
+ * NodeID T ChipID
+ * | | | |
+ * |___|___|___|___|___|___|
+ *
+ * Where T is the "torrent" bit and is 0 for P7 chips and 1 for
+ * directly XSCOM'able IO chips such as Torrent
+ *
+ * This macro converts a PIR to a GCID
+ */
+#define P7_PIR2GCID(pir) ({ \
+ uint32_t _pir = pir; \
+ ((_pir >> 4) & 0x38) | ((_pir >> 5) & 0x3); })
+
+#define P7_PIR2COREID(pir) (((pir) >> 2) & 0x7)
+
+#define P7_PIR2THREADID(pir) ((pir) & 0x3)
+
+/*
+ * P8 GCID
+ * -------
+ *
+ * Global chip ID is a 6 bit number:
+ *
+ * NodeID ChipID
+ * | | |
+ * |___|___|___|___|___|___|
+ *
+ * The difference with P7 is the absence of T bit, the ChipID
+ * is 3 bits long. The GCID is thus the same as the high bits
+ * if the PIR
+ */
+#define P8_PIR2GCID(pir) (((pir) >> 7) & 0x3f)
+
+#define P8_PIR2COREID(pir) (((pir) >> 3) & 0xf)
+
+#define P8_PIR2THREADID(pir) ((pir) & 0x7)
+
+struct dt_node;
+struct centaur_chip;
+
+/* Chip type */
+enum proc_chip_type {
+ PROC_CHIP_UNKNOWN,
+ PROC_CHIP_P7,
+ PROC_CHIP_P7P,
+ PROC_CHIP_P8_MURANO,
+ PROC_CHIP_P8_VENICE,
+};
+
+#define MAX_CHIPS (1 << 6) /* 6-bit chip ID */
+
+/*
+ * For each chip in the system, we maintain this structure
+ *
+ * This contains fields used by different modules including
+ * modules in hw/ but is handy to keep per-chip data
+ */
+struct proc_chip {
+ uint32_t id; /* HW Chip ID (GCID) */
+ struct dt_node *devnode; /* "xscom" chip node */
+
+ /* These are only initialized after xcom_init */
+ enum proc_chip_type type;
+ uint32_t ec_level; /* 0xMm (DD1.0 = 0x10) */
+
+ /* Those two values are only populated on machines with an FSP
+ * dbob_id = Drawer/Block/Octant/Blade (DBOBID)
+ * pcid = HDAT processor_chip_id
+ */
+ uint32_t dbob_id;
+ uint32_t pcid;
+
+ /* Used by hw/xscom.c */
+ uint64_t xscom_base;
+
+ /* Used by hw/lpc.c */
+ uint32_t lpc_xbase;
+ struct lock lpc_lock;
+ uint8_t lpc_fw_idsel;
+ uint8_t lpc_fw_rdsz;
+
+ /* Used by hw/slw.c */
+ uint64_t slw_base;
+ uint64_t slw_bar_size;
+ uint64_t slw_image_size;
+
+ /* Used by hw/homer.c */
+ uint64_t homer_base;
+ uint64_t homer_size;
+ uint64_t occ_common_base;
+ uint64_t occ_common_size;
+
+ /* Used by hw/centaur.c */
+ struct centaur_chip *centaurs;
+};
+
+extern uint32_t pir_to_chip_id(uint32_t pir);
+extern uint32_t pir_to_core_id(uint32_t pir);
+extern uint32_t pir_to_thread_id(uint32_t pir);
+
+extern struct proc_chip *next_chip(struct proc_chip *chip);
+
+#define for_each_chip(__c) for (__c=next_chip(NULL); __c; __c=next_chip(__c))
+
+extern struct proc_chip *get_chip(uint32_t chip_id);
+
+extern void init_chips(void);
+
+
+#endif /* __CHIP_H */
+
diff --git a/include/chiptod.h b/include/chiptod.h
new file mode 100644
index 0000000..ef34927
--- /dev/null
+++ b/include/chiptod.h
@@ -0,0 +1,28 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CHIPTOD_H
+#define __CHIPTOD_H
+
+/* The ChipTOD is the HW facility that maintains a synchronized
+ * time base across the fabric.
+ */
+
+extern void chiptod_init(u32 master_cpu);
+
+extern bool chiptod_wakeup_resync(void);
+
+#endif /* __CHIPTOD_H */
diff --git a/include/codeupdate.h b/include/codeupdate.h
new file mode 100644
index 0000000..04f5471
--- /dev/null
+++ b/include/codeupdate.h
@@ -0,0 +1,236 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __CODEUPDATE_H
+#define __CODEUPDATE_H
+
+/* Flash SG list version */
+#define SG_LIST_VERSION (1UL)
+
+/* LID size <= 16M */
+#define LID_MAX_SIZE 0x1000000
+
+/* Delete all LIDs in */
+#define DEL_UPD_SIDE_LIDS 0xFFFFFFFF
+
+/* System parameter values used in code update validation */
+#define INBAND_UPDATE_ALLOWED 0x01
+#define PLATFORM_HMC_MANAGED 0x01
+#define FW_LICENSE_ACCEPT 0x01
+
+/* Running image side */
+#define FW_IPL_SIDE_TEMP 0x01
+#define FW_IPL_SIDE_PERM 0x00
+
+/* Manage operations */
+#define OPAL_REJECT_TMP_SIDE 0
+#define OPAL_COMMIT_TMP_SIDE 1
+
+/* Validate image size */
+#define VALIDATE_BUF_SIZE 4096
+
+/* Code update operation status */
+#define OPAL_INVALID_IMAGE -1003 /* Unacceptable image */
+#define OPAL_ACTIVE_SIDE_ERR -9001
+#define OPAL_FLASH_NO_AUTH -9002
+
+/* Validate image update result tokens */
+#define VALIDATE_TMP_UPDATE 0 /* T side will be updated */
+#define VALIDATE_FLASH_AUTH 1 /* Partition does not have authority */
+#define VALIDATE_INVALID_IMG 2 /* Candidate image is not valid */
+#define VALIDATE_CUR_UNKNOWN 3 /* Current fixpack level is unknown */
+/*
+ * Current T side will be committed to P side before being replace with new
+ * image, and the new image is downlevel from current image
+ */
+#define VALIDATE_TMP_COMMIT_DL 4
+/*
+ * Current T side will be committed to P side before being replaced with new
+ * image
+ */
+#define VALIDATE_TMP_COMMIT 5
+/*
+ * T side will be updated with a downlevel image
+ */
+#define VALIDATE_TMP_UPDATE_DL 6
+/*
+ * The candidate image's release date is later than the system's firmware
+ * service entitlement date - service warranty period has expired
+ */
+#define VALIDATE_OUT_OF_WRNTY 7
+
+/* default version */
+#define FW_VERSION_UNKNOWN "UNKNOWN"
+
+/* Actual size of MI & ML keyword including NULL */
+#define MI_KEYWORD_SIZE 10
+#define ML_KEYWORD_SIZE 9
+
+/* Firmware image VPD data */
+struct fw_image_vpd {
+ char MI_keyword[MI_KEYWORD_SIZE]; /* NNSSS_FFF */
+ char ext_fw_id[ML_KEYWORD_SIZE]; /* FWxxx.yy */
+};
+
+/* Master LID header */
+struct master_lid_header {
+ char key[3]; /* "MLH" */
+ uint8_t version; /* 0x02 */
+ uint16_t headerSize;
+ uint16_t entrySize;
+ uint8_t reserved[56];
+};
+
+/* LID index entry */
+struct lid_index_entry {
+ uint32_t id;
+ uint32_t size;
+ uint32_t offset;
+ uint32_t crc;
+};
+
+/* SP flags */
+#define FW_ONE_OFF_SP 0x80000000
+#define FW_EMERGENCY_SP 0x40000000
+
+/*
+ * SP GA date
+ *
+ * sp_flag addr = header->data + header->ext_fw_id_size
+ */
+struct update_image_ga_date {
+ uint32_t sp_flag;
+ char sp_ga_date[8]; /* YYYYMMDD */
+};
+
+/* Image magic number */
+#define IMAGE_MAGIC_NUMBER 0x5549
+
+/* Image header structure */
+struct update_image_header {
+ uint16_t magic;
+ uint16_t version;
+ uint32_t package_size;
+ uint32_t crc;
+ uint16_t lid_index_offset;
+ uint16_t number_lids;
+ uint16_t package_flags;
+ uint16_t MI_keyword_size;
+ char MI_keyword_data[40];
+ uint16_t ext_fw_id_size;
+ /* Rest of the image data including ext fw id, sp flags */
+ char data[];
+};
+
+/* FipS header */
+struct fips_header {
+ uint16_t magic;
+ uint16_t version;
+ uint32_t lid_id;
+ uint32_t lid_date; /* YYYYMMDD */
+ uint16_t lid_time; /* HHMM */
+ uint16_t lid_class;
+ uint32_t crc;
+ uint32_t lid_size; /* Number of bytes below header */
+ uint32_t header_size;
+ uint8_t mtd_number;
+ uint8_t valid; /* 1 = valid, 0 = invalid */
+ uint8_t reserved;
+ uint8_t lid_info_size;
+ char lid_info[64]; /* code level */
+ uint32_t update_date; /* YYYYMMDD */
+ uint16_t update_time; /* HHMM */
+ uint16_t phylum_len;
+ uint8_t lid_phylum[];
+};
+
+/* Approximate LID size */
+#define MASTER_LID_SIZE 0x5000
+/*
+ * Note:
+ * Doc indicates non-SP LIDs size is 0-8MB. However
+ * in reality marker LID size less than 4k. Allocating
+ * 8k to give some breathing space.
+ */
+#define MARKER_LID_SIZE 0x00002000
+
+/* Common marker LID no */
+#define P_COM_MARKER_LID_ID 0x80A00001
+#define T_COM_MARKER_LID_ID (P_COM_MARKER_LID_ID | ADJUST_T_SIDE_LID_NO)
+
+/*
+ * Common marker LID structure
+ *
+ * Note that we are populating only required sections,
+ * not all ADF sections in common marker LID.
+ */
+struct com_marker_header {
+ uint32_t version;
+ uint32_t MI_offset; /* Offset to MI section */
+ uint32_t iseries_offset;
+};
+
+/* MI Keyword section */
+struct com_marker_mi_section {
+ uint32_t MI_size;
+ char MI_keyword[40]; /* MI Keyword */
+ char lst_disrupt_fix_lvl[3];
+ char skip[21]; /* Skip not interested fields */
+ uint32_t adf_offset; /* Offset to ADF section */
+};
+
+/* Additional Data Fields */
+struct com_marker_adf_sec {
+ uint32_t adf_cnt; /* ADF count */
+ char adf_data[]; /* ADF data */
+};
+
+/* ADF common header */
+struct com_marker_adf_header {
+ uint32_t size; /* Section size */
+ uint32_t name; /* Section name */
+};
+
+/*
+ * Service Pack Nomenclature ADF
+ *
+ * Service pack release name.
+ */
+#define ADF_NAME_SP 0x53504E4D /* SPNM */
+struct com_marker_adf_sp
+{
+ struct com_marker_adf_header header;
+ uint32_t sp_name_offset; /* Offset from start of ADF */
+ uint32_t sp_name_size;
+ uint32_t skip[4]; /* Skip rest of fields */
+};
+
+/*
+ * Firmware IP Protection ADF
+ *
+ * Service Pack flags and GA date.
+ */
+#define ADF_NAME_FW_IP 0x46495050 /* FIPP */
+struct com_marker_fw_ip {
+ struct com_marker_adf_header header;
+ uint32_t sp_flag_offset; /* Offset from start of ADF */
+ uint32_t sp_flag_size;
+ uint32_t sp_ga_offset; /* Offset from start of ADF*/
+ uint32_t sp_ga_size;
+};
+
+#endif /* __CODEUPDATE_H */
diff --git a/include/compiler.h b/include/compiler.h
new file mode 100644
index 0000000..c1557d8
--- /dev/null
+++ b/include/compiler.h
@@ -0,0 +1,50 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __COMPILER_H
+#define __COMPILER_H
+
+#ifndef __ASSEMBLY__
+
+#include <stddef.h>
+
+/* Macros for various compiler bits and pieces */
+#define __packed __attribute__((packed))
+#define __align(x) __attribute__((__aligned__(x)))
+#define __unused __attribute__((unused))
+#define __used __attribute__((used))
+#define __section(x) __attribute__((__section__(x)))
+#define __noreturn __attribute__((noreturn))
+/* not __const as this has a different meaning (const) */
+#define __attrconst __attribute__((const))
+
+#if 0 /* Provided by gcc stddef.h */
+#define offsetof(type,m) __builtin_offsetof(type,m)
+#endif
+
+/* Compiler barrier */
+static inline void barrier(void)
+{
+ asm volatile("" : : : "memory");
+}
+
+#endif /* __ASSEMBLY__ */
+
+/* Stringification macro */
+#define __tostr(x) #x
+#define tostr(x) __tostr(x)
+
+#endif /* __COMPILER_H */
diff --git a/include/config.h b/include/config.h
new file mode 100644
index 0000000..78b63fe
--- /dev/null
+++ b/include/config.h
@@ -0,0 +1,93 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define HAVE_TYPEOF 1
+#define HAVE_BUILTIN_TYPES_COMPATIBLE_P 1
+
+/* Keep -Wundef happy by defining whatever isn't on commandline to 0 */
+#if defined(HAVE_LITTLE_ENDIAN) && HAVE_LITTLE_ENDIAN
+#define HAVE_BIG_ENDIAN 0
+#endif
+#if defined(HAVE_BIG_ENDIAN) && HAVE_BIG_ENDIAN
+#define HAVE_LITTLE_ENDIAN 0
+#endif
+
+/* We don't have a byteswap.h, and thus no bswap_64 */
+#define HAVE_BYTESWAP_H 0
+#define HAVE_BSWAP_64 0
+
+/*
+ * Build options.
+ */
+
+/* Enable lock debugging */
+#define DEBUG_LOCKS 1
+
+/* Enable malloc debugging */
+#define DEBUG_MALLOC 1
+
+/* Enable OPAL entry point tracing */
+//#define OPAL_TRACE_ENTRY 1
+
+/* Enable tracing of event state change */
+//#define OPAL_TRACE_EVT_CHG 1
+
+/* Enable various levels of OPAL_console debug */
+//#define OPAL_DEBUG_CONSOLE_IO 1
+//#define OPAL_DEBUG_CONSOLE_POLL 1
+
+/* Enable this for mambo console */
+//#define MAMBO_CONSOLE 1
+
+/* Enable this to hookup SkiBoot log to the DVS console */
+#define DVS_CONSOLE 1
+
+/* Enable this to force the dummy console to the kernel.
+ * (ie, an OPAL console that injects into skiboot own console)
+ * Where possible, leave this undefined and enable it dynamically using
+ * the chosen->sapphire,enable-dummy-console in the device tree.
+ *
+ * Note: This only gets enabled if there is no FSP console. If there
+ * is one it always takes over for now. This also cause the LPC UART
+ * node to be marked "reserved" so Linux doesn't instanciate a 8250
+ * driver for it.
+ */
+//#define FORCE_DUMMY_CONSOLE 1
+
+/* Enable this to do fast resets. Currently unreliable... */
+//#define ENABLE_FAST_RESET 1
+
+/* Enable this to make fast reboot clear memory */
+//#define FAST_REBOOT_CLEARS_MEMORY 1
+
+/* Enable this to disable setting of the output pending event when
+ * sending things on the console. The FSP is very slow to consume
+ * and older kernels wait after each character during early boot so
+ * things get very slow. Eventually, we may want to create an OPAL
+ * API for the kernel to activate or deactivate that functionality
+ */
+#define DISABLE_CON_PENDING_EVT 1
+
+/* Configure this to provide some additional kernel command line
+ * arguments to the bootloader
+ */
+//#define KERNEL_COMMAND_LINE "debug"
+
+#endif /* __CONFIG_H */
+
diff --git a/include/console.h b/include/console.h
new file mode 100644
index 0000000..791f770
--- /dev/null
+++ b/include/console.h
@@ -0,0 +1,68 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CONSOLE_H
+#define __CONSOLE_H
+
+#include <lock.h>
+
+/*
+ * Our internal console uses the format of BML new-style in-memory
+ * console and supports input for setups without a physical console
+ * facility or FSP.
+ *
+ * (This is v3 of the format, the previous one sucked)
+ */
+struct memcons {
+ uint64_t magic;
+#define MEMCONS_MAGIC 0x6630696567726173
+ uint64_t obuf_phys;
+ uint64_t ibuf_phys;
+ uint32_t obuf_size;
+ uint32_t ibuf_size;
+ uint32_t out_pos;
+#define MEMCONS_OUT_POS_WRAP 0x80000000u
+#define MEMCONS_OUT_POS_MASK 0x00ffffffu
+ uint32_t in_prod;
+ uint32_t in_cons;
+};
+
+extern struct memcons memcons;
+
+#define INMEM_CON_IN_LEN 16
+#define INMEM_CON_OUT_LEN (INMEM_CON_LEN - INMEM_CON_IN_LEN)
+
+/* Console driver */
+struct con_ops {
+ size_t (*write)(const char *buf, size_t len);
+ size_t (*read)(char *buf, size_t len);
+};
+
+extern struct lock con_lock;
+
+extern bool dummy_console_enabled(void);
+extern void force_dummy_console(void);
+extern bool flush_console(void);
+extern bool __flush_console(void);
+extern void set_console(struct con_ops *driver);
+
+extern void clear_console(void);
+extern void memcons_add_properties(void);
+extern void dummy_console_add_nodes(void);
+
+extern bool uart_console_poll(void);
+
+#endif /* __CONSOLE_H */
diff --git a/include/cpu.h b/include/cpu.h
new file mode 100644
index 0000000..7ea88b6
--- /dev/null
+++ b/include/cpu.h
@@ -0,0 +1,207 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CPU_H
+#define __CPU_H
+
+#include <processor.h>
+#include <ccan/list/list.h>
+#include <lock.h>
+#include <device.h>
+#include <opal.h>
+
+/*
+ * cpu_thread is our internal structure representing each
+ * thread in the system
+ */
+
+enum cpu_thread_state {
+ cpu_state_no_cpu = 0, /* Nothing there */
+ cpu_state_unknown, /* In PACA, not called in yet */
+ cpu_state_unavailable, /* Not available */
+ cpu_state_present, /* Assumed to spin in asm entry */
+ cpu_state_active, /* Secondary called in */
+ cpu_state_os, /* Under OS control */
+ cpu_state_disabled, /* Disabled by us due to error */
+ cpu_state_rvwinkle, /* Doing an rvwinkle cycle */
+};
+
+struct cpu_job;
+
+struct cpu_thread {
+ uint32_t pir;
+ uint32_t server_no;
+ uint32_t chip_id;
+ bool is_secondary;
+ bool current_hile;
+ struct cpu_thread *primary;
+ enum cpu_thread_state state;
+ struct dt_node *node;
+ struct opal_machine_check_event mc_event;
+ struct trace_info *trace;
+ uint64_t save_r1;
+ void *icp_regs;
+ uint32_t con_suspend;
+ bool con_need_flush;
+ uint32_t hbrt_spec_wakeup; /* primary only */
+
+ struct lock job_lock;
+ struct list_head job_queue;
+};
+
+/* This global is set to 1 to allow secondaries to callin,
+ * typically set after the primary has allocated the cpu_thread
+ * array and stacks
+ */
+extern unsigned long cpu_secondary_start;
+
+/* Max PIR in the system */
+extern unsigned int cpu_max_pir;
+
+/* Max # of threads per core */
+extern unsigned int cpu_thread_count;
+
+/* Boot CPU. */
+extern struct cpu_thread *boot_cpu;
+
+/* Initialize CPUs */
+void pre_init_boot_cpu(void);
+void init_boot_cpu(void);
+void init_all_cpus(void);
+
+/* This brings up our secondaries */
+extern void cpu_bringup(void);
+
+/* This is called by secondaries as they call in */
+extern void cpu_callin(struct cpu_thread *cpu);
+
+/* For cpus which fail to call in. */
+extern void cpu_remove_node(const struct cpu_thread *t);
+
+/* Find CPUs using different methods */
+extern struct cpu_thread *find_cpu_by_chip_id(u32 chip_id);
+extern struct cpu_thread *find_cpu_by_node(struct dt_node *cpu);
+extern struct cpu_thread *find_cpu_by_server(u32 server_no);
+extern struct cpu_thread *find_cpu_by_pir(u32 pir);
+
+extern struct dt_node *get_cpu_node(u32 pir);
+
+/* Iterator */
+extern struct cpu_thread *first_cpu(void);
+extern struct cpu_thread *next_cpu(struct cpu_thread *cpu);
+
+/* WARNING: CPUs that have been picked up by the OS are no longer
+ * appearing as available and can not have jobs scheduled
+ * on them. Essentially that means that after the OS is
+ * fully started, all CPUs are seen as unavailable from
+ * this API standpoint.
+ */
+
+static inline bool cpu_is_available(struct cpu_thread *cpu)
+{
+ return cpu->state == cpu_state_active ||
+ cpu->state == cpu_state_rvwinkle;
+}
+
+extern struct cpu_thread *first_available_cpu(void);
+extern struct cpu_thread *next_available_cpu(struct cpu_thread *cpu);
+
+#define for_each_cpu(cpu) \
+ for (cpu = first_cpu(); cpu; cpu = next_cpu(cpu))
+
+#define for_each_available_cpu(cpu) \
+ for (cpu = first_available_cpu(); cpu; cpu = next_available_cpu(cpu))
+
+extern struct cpu_thread *first_available_core_in_chip(u32 chip_id);
+extern struct cpu_thread *next_available_core_in_chip(struct cpu_thread *cpu, u32 chip_id);
+
+#define for_each_available_core_in_chip(core, chip_id) \
+ for (core = first_available_core_in_chip(chip_id); core; \
+ core = next_available_core_in_chip(core, chip_id))
+
+/* Return the caller CPU (only after init_cpu_threads) */
+register struct cpu_thread *__this_cpu asm("r13");
+static inline struct cpu_thread *this_cpu(void)
+{
+ return __this_cpu;
+}
+
+/* Get the thread # of a cpu within the core */
+static inline uint32_t cpu_get_thread_index(struct cpu_thread *cpu)
+{
+ return cpu->pir - cpu->primary->pir;
+}
+
+/* Get the core # of a cpu within the core */
+extern uint32_t cpu_get_core_index(struct cpu_thread *cpu);
+
+/* Get the PIR of thread 0 of the same core */
+static inline uint32_t cpu_get_thread0(struct cpu_thread *cpu)
+{
+ return cpu->primary->pir;
+}
+
+static inline bool cpu_is_thread0(struct cpu_thread *cpu)
+{
+ return cpu->primary == cpu;
+}
+
+static inline bool cpu_is_sibling(struct cpu_thread *cpu1,
+ struct cpu_thread *cpu2)
+{
+ return cpu1->primary == cpu2->primary;
+}
+
+/* Called when some error condition requires disabling a core */
+void cpu_disable_all_threads(struct cpu_thread *cpu);
+
+/* Allocate & queue a job on target CPU */
+extern struct cpu_job *__cpu_queue_job(struct cpu_thread *cpu,
+ void (*func)(void *data), void *data,
+ bool no_return);
+
+static inline struct cpu_job *cpu_queue_job(struct cpu_thread *cpu,
+ void (*func)(void *data),
+ void *data)
+{
+ return __cpu_queue_job(cpu, func, data, false);
+}
+
+
+/* Poll job status, returns true if completed */
+extern bool cpu_poll_job(struct cpu_job *job);
+
+/* Synchronously wait for a job to complete, this will
+ * continue handling the FSP mailbox if called from the
+ * boot CPU. Set free_it to free it automatically.
+ */
+extern void cpu_wait_job(struct cpu_job *job, bool free_it);
+
+/* Free a CPU job, only call on a completed job */
+extern void cpu_free_job(struct cpu_job *job);
+
+/* Called by init to process jobs */
+extern void cpu_process_jobs(void);
+
+static inline void cpu_give_self_os(void)
+{
+ __this_cpu->state = cpu_state_os;
+}
+
+extern void *cpu_stack_bottom(unsigned int pir);
+extern void *cpu_stack_top(unsigned int pir);
+
+#endif /* __CPU_H */
diff --git a/include/device.h b/include/device.h
new file mode 100644
index 0000000..65ceef4
--- /dev/null
+++ b/include/device.h
@@ -0,0 +1,233 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DEVICE_H
+#define __DEVICE_H
+#include <ccan/list/list.h>
+#include <ccan/short_types/short_types.h>
+
+/* Any property or node with this prefix will not be passed to the kernel. */
+#define DT_PRIVATE "skiboot,"
+
+/*
+ * An in-memory representation of a node in the device tree.
+ *
+ * This is trivially flattened into an fdt.
+ *
+ * Note that the add_* routines will make a copy of the name if it's not
+ * a read-only string (ie. usually a string literal).
+ */
+struct dt_property {
+ struct list_node list;
+ const char *name;
+ size_t len;
+ char prop[/* len */];
+};
+
+struct dt_node {
+ const char *name;
+ struct list_node list;
+ struct list_head properties;
+ struct list_head children;
+ struct dt_node *parent;
+ u32 phandle;
+};
+
+/* This is shared with device_tree.c .. make it static when
+ * the latter is gone (hopefully soon)
+ */
+extern u32 last_phandle;
+
+extern struct dt_node *dt_root;
+extern struct dt_node *dt_chosen;
+
+/* Create a root node: ie. a parentless one. */
+struct dt_node *dt_new_root(const char *name);
+
+/* Graft a root node into this tree. */
+bool dt_attach_root(struct dt_node *parent, struct dt_node *root);
+
+/* Add a child node. */
+struct dt_node *dt_new(struct dt_node *parent, const char *name);
+struct dt_node *dt_new_addr(struct dt_node *parent, const char *name,
+ uint64_t unit_addr);
+struct dt_node *dt_new_2addr(struct dt_node *parent, const char *name,
+ uint64_t unit_addr0, uint64_t unit_addr1);
+
+/* Add a property node, various forms. */
+struct dt_property *dt_add_property(struct dt_node *node,
+ const char *name,
+ const void *val, size_t size);
+struct dt_property *dt_add_property_string(struct dt_node *node,
+ const char *name,
+ const char *value);
+struct dt_property *dt_add_property_nstr(struct dt_node *node,
+ const char *name,
+ const char *value, unsigned int vlen);
+
+/* Given out enough GCC extensions, we will achieve enlightenment! */
+#define dt_add_property_strings(node, name, ...) \
+ __dt_add_property_strings((node), ((name)), \
+ sizeof((const char *[]) { __VA_ARGS__ })/sizeof(const char *), \
+ __VA_ARGS__)
+
+struct dt_property *__dt_add_property_strings(struct dt_node *node,
+ const char *name,
+ int count, ...);
+
+/* Given out enough GCC extensions, we will achieve enlightenment! */
+#define dt_add_property_cells(node, name, ...) \
+ __dt_add_property_cells((node), ((name)), \
+ sizeof((u32[]) { __VA_ARGS__ })/sizeof(u32), \
+ __VA_ARGS__)
+
+struct dt_property *__dt_add_property_cells(struct dt_node *node,
+ const char *name,
+ int count, ...);
+
+#define dt_add_property_u64s(node, name, ...) \
+ __dt_add_property_u64s((node), ((name)), \
+ sizeof((u64[]) { __VA_ARGS__ })/sizeof(u64), \
+ __VA_ARGS__)
+
+struct dt_property *__dt_add_property_u64s(struct dt_node *node,
+ const char *name,
+ int count, ...);
+
+static inline struct dt_property *dt_add_property_u64(struct dt_node *node,
+ const char *name, u64 val)
+{
+ return dt_add_property_cells(node, name, (u32)(val >> 32), (u32)val);
+}
+
+void dt_del_property(struct dt_node *node, struct dt_property *prop);
+
+/* Warning: moves *prop! */
+void dt_resize_property(struct dt_property **prop, size_t len);
+
+u32 dt_property_get_cell(const struct dt_property *prop, u32 index);
+
+/* First child of this node. */
+struct dt_node *dt_first(const struct dt_node *root);
+
+/* Return next node, or NULL. */
+struct dt_node *dt_next(const struct dt_node *root, const struct dt_node *prev);
+
+/* Iterate nodes */
+#define dt_for_each_node(root, node) \
+ for (node = dt_first(root); node; node = dt_next(root, node))
+
+#define dt_for_each_child(parent, node) \
+ list_for_each(&parent->children, node, list)
+
+/* Find a string in a string list */
+bool dt_prop_find_string(const struct dt_property *p, const char *s);
+
+/* Check a compatible property */
+bool dt_node_is_compatible(const struct dt_node *node, const char *compat);
+
+/* Find a node based on compatible property */
+struct dt_node *dt_find_compatible_node(struct dt_node *root,
+ struct dt_node *prev,
+ const char *compat);
+
+#define dt_for_each_compatible(root, node, compat) \
+ for (node = NULL; \
+ (node = dt_find_compatible_node(root, node, compat)) != NULL;)
+
+struct dt_node *dt_find_compatible_node_on_chip(struct dt_node *root,
+ struct dt_node *prev,
+ const char *compat,
+ uint32_t chip_id);
+
+#define dt_for_each_compatible_on_chip(root, node, compat, chip_id) \
+ for (node = NULL; \
+ (node = dt_find_compatible_node_on_chip(root, node,\
+ compat, chip_id)) != NULL;)
+
+/* Build the full path for a node. Return a new block of memory, caller
+ * shall free() it
+ */
+char *dt_get_path(const struct dt_node *node);
+
+/* Find a node by path */
+struct dt_node *dt_find_by_path(struct dt_node *root, const char *path);
+
+/* Find a node by phandle */
+struct dt_node *dt_find_by_phandle(struct dt_node *root, u32 phandle);
+
+/* Find a property by name. */
+const struct dt_property *dt_find_property(const struct dt_node *node,\
+ const char *name);
+const struct dt_property *dt_require_property(const struct dt_node *node,
+ const char *name, int wanted_len);
+
+/* non-const variant */
+struct dt_property *__dt_find_property(struct dt_node *node, const char *name);
+
+/* Find a property by name, check if it's the same as val. */
+bool dt_has_node_property(const struct dt_node *node,
+ const char *name, const char *val);
+
+/* Free a node (and any children). */
+void dt_free(struct dt_node *node);
+
+/* Parse an initial fdt */
+void dt_expand(const void *fdt);
+int dt_expand_node(struct dt_node *node, const void *fdt, int fdt_node);
+
+/* Simplified accessors */
+u64 dt_prop_get_u64(const struct dt_node *node, const char *prop);
+u64 dt_prop_get_u64_def(const struct dt_node *node, const char *prop, u64 def);
+u32 dt_prop_get_u32(const struct dt_node *node, const char *prop);
+u32 dt_prop_get_u32_def(const struct dt_node *node, const char *prop, u32 def);
+const void *dt_prop_get(const struct dt_node *node, const char *prop);
+const void *dt_prop_get_def(const struct dt_node *node, const char *prop,
+ void *def);
+const void *dt_prop_get_def_size(const struct dt_node *node, const char *prop,
+ void *def, size_t *len);
+u32 dt_prop_get_cell(const struct dt_node *node, const char *prop, u32 cell);
+u32 dt_prop_get_cell_def(const struct dt_node *node, const char *prop, u32 cell, u32 def);
+
+/* Parsing helpers */
+u32 dt_n_address_cells(const struct dt_node *node);
+u32 dt_n_size_cells(const struct dt_node *node);
+u64 dt_get_number(const void *pdata, unsigned int cells);
+
+/* Find an ibm,chip-id property in this node; if not found, walk up the parent
+ * nodes. Returns -1 if no chip-id property exists. */
+u32 dt_get_chip_id(const struct dt_node *node);
+
+/* Address accessors ("reg" properties parsing). No translation,
+ * only support "simple" address forms (1 or 2 cells). Asserts
+ * if address doesn't exist
+ */
+u64 dt_get_address(const struct dt_node *node, unsigned int index,
+ u64 *out_size);
+
+/* Count "reg" property entries */
+unsigned int dt_count_addresses(const struct dt_node *node);
+
+/* Address translation
+ *
+ * WARNING: Current implementation is simplified and will not
+ * handle complex address formats with address space indicators
+ * nor will it handle "ranges" translations yet... (XX TODO)
+ */
+u64 dt_translate_address(const struct dt_node *node, unsigned int index,
+ u64 *out_size);
+
+#endif /* __DEVICE_H */
diff --git a/include/device_tree.h b/include/device_tree.h
new file mode 100644
index 0000000..d04f20a
--- /dev/null
+++ b/include/device_tree.h
@@ -0,0 +1,35 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DEVICE_TREE_H
+#define __DEVICE_TREE_H
+#include <stdint.h>
+
+/* Note: Device tree creation has no locks. It's assumed to be done
+ * by a single processor in a non racy way
+ */
+void *create_dtb(const struct dt_node *root);
+
+/* Helpers to cache errors in fdt; use this instead of fdt_* */
+uint32_t dt_begin_node(const char *name); /* returns phandle */
+void dt_property_string(const char *name, const char *value);
+void dt_property_cell(const char *name, u32 cell);
+void dt_property_cells(const char *name, int count, ...);
+void dt_property(const char *name, const void *val, size_t size);
+void dt_end_node(void);
+
+
+#endif /* __DEVICE_TREE_H */
diff --git a/include/ec/config.h b/include/ec/config.h
new file mode 100644
index 0000000..201ccac
--- /dev/null
+++ b/include/ec/config.h
@@ -0,0 +1,82 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file config.H
+ *
+ * @brief Definitions for EC configuration values.
+ *
+ */
+
+#ifndef __EC_CONFIG_H_
+#define __EC_CONFIG_H_
+
+#include <stdint.h>
+
+#define EC_RTC_PORT_BASE (0x70) // RTC/CMOS LPC base address
+#define EC_RTC_BLOCK_SIZE (512) // Size of addressable data in RTC
+#define EC_RTC_CENTURY (1) // 1 if century format is enabled
+#if EC_RTC_CENTURY
+#define EC_RTC_BBRAM_OFFSET (0x33) // Offset of NV data (= size of calendar)
+#else
+#define EC_RTC_BBRAM_OFFSET (0x0E) // Offset of NV data (= size of calendar)
+#endif // #if EC_RTC_CENTURY
+
+#define EC_RTCDD_READ_TRIES (2) // Times to try the RTC if updating
+#define EC_RTCDD_RETRY_DELAY (300000) // Delay between RTC read retries in ns
+ // based on update time of 244 + 30.5 µs
+
+#define EC_GPIO_INDEX 0x200
+#define EC_GPIO_DATA 0x201
+#define EC_GPIO_NUM_PORTS 17
+#define EC_GPIO_PORT_SKIP 4
+
+#define EC_GPIO_DATA_OFFSET 0x0
+#define EC_GPIO_DDR_OFFSET 0x1
+#define EC_GPIO_PIN_OFFSET 0x2
+#define EC_GPIO_PUP_OFFSET 0x3
+
+typedef enum EcGpioPort {
+ EC_GPIO_PORT_A = 0,
+ EC_GPIO_PORT_B = 1,
+ EC_GPIO_PORT_C = 2,
+ EC_GPIO_PORT_D = 3,
+ EC_GPIO_PORT_E = 4,
+ EC_GPIO_PORT_F = 5,
+ EC_GPIO_PORT_G = 6,
+ EC_GPIO_PORT_H = 7,
+ // skip port I
+ EC_GPIO_PORT_J = 8,
+ EC_GPIO_PORT_K = 9,
+ EC_GPIO_PORT_L = 10,
+ EC_GPIO_PORT_M = 11,
+ EC_GPIO_PORT_N = 12,
+ // skip port O
+ EC_GPIO_PORT_P = 13,
+ EC_GPIO_PORT_Q = 14,
+ EC_GPIO_PORT_R = 15,
+ EC_GPIO_PORT_S = 16,
+} EcGpioPort;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void ec_outb(uint16_t, uint8_t);
+uint8_t ec_inb(uint16_t);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __EC_CONFIG_H_
diff --git a/include/ec/gpio.h b/include/ec/gpio.h
new file mode 100644
index 0000000..82a9343
--- /dev/null
+++ b/include/ec/gpio.h
@@ -0,0 +1,53 @@
+/* Copyright 2013-2014 Google Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file gpio.h
+ *
+ * @brief Public interface of the EC GPIO device driver
+ *
+ */
+
+#ifndef __EC_GPIO_H_
+#define __EC_GPIO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EC_GPIO_INPUT 0
+#define EC_GPIO_OUTPUT 1
+#define EC_GPIO_PULLUP_DISABLE 0
+#define EC_GPIO_PULLUP_ENABLE 1
+
+// Sets up a GPIO as output or input.
+// Returns: <0 on error
+int ec_gpio_setup(EcGpioPort port, uint8_t pin,
+ int is_output, int pullup_enable);
+
+// Reads the current value of an input GPIO.
+// Returns: GPIO value (0,1) or <0 on error.
+int ec_gpio_read(EcGpioPort port, uint8_t pin);
+
+// Sets the driving value of an output GPIO. Port should already be set
+// to output mode.
+// Returns: <0 on error
+int ec_gpio_set(EcGpioPort port, uint8_t pin, int val);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __EC_GPIO_H_
diff --git a/include/elf.h b/include/elf.h
new file mode 100644
index 0000000..0a52f3e
--- /dev/null
+++ b/include/elf.h
@@ -0,0 +1,135 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ELF_H
+#define __ELF_H
+
+#include <stdint.h>
+
+/* Generic ELF header */
+struct elf_hdr {
+ uint32_t ei_ident;
+#define ELF_IDENT 0x7F454C46
+ uint8_t ei_class;
+#define ELF_CLASS_32 1
+#define ELF_CLASS_64 2
+ uint8_t ei_data;
+#define ELF_DATA_LSB 1
+#define ELF_DATA_MSB 2
+ uint8_t ei_version;
+ uint8_t ei_pad[9];
+ uint16_t e_type;
+ uint16_t e_machine;
+#define ELF_MACH_PPC32 0x14
+#define ELF_MACH_PPC64 0x15
+ uint32_t e_version;
+};
+
+/* 64-bit ELF header */
+struct elf64_hdr {
+ uint32_t ei_ident;
+ uint8_t ei_class;
+ uint8_t ei_data;
+ uint8_t ei_version;
+ uint8_t ei_pad[9];
+ uint16_t e_type;
+ uint16_t e_machine;
+ uint32_t e_version;
+ uint64_t e_entry;
+ uint64_t e_phoff;
+ uint64_t e_shoff;
+ uint32_t e_flags;
+ uint16_t e_ehsize;
+ uint16_t e_phentsize;
+ uint16_t e_phnum;
+ uint16_t e_shentsize;
+ uint16_t e_shnum;
+ uint16_t e_shstrndx;
+};
+
+/* 64-bit ELF program header */
+struct elf64_phdr {
+ uint32_t p_type;
+#define ELF_PTYPE_LOAD 1
+ uint32_t p_flags;
+#define ELF_PFLAGS_R 0x4
+#define ELF_PFLAGS_W 0x2
+#define ELF_PFLAGS_X 0x1
+ uint64_t p_offset;
+ uint64_t p_vaddr;
+ uint64_t p_paddr;
+ uint64_t p_filesz;
+ uint64_t p_memsz;
+ uint64_t p_align;
+};
+
+/* Some relocation related stuff used in relocate.c */
+struct elf64_dyn {
+ int64_t d_tag;
+#define DT_NULL 0
+#define DT_RELA 7
+#define DT_RELASZ 8
+#define DT_RELAENT 9
+#define DT_RELACOUNT 0x6ffffff9
+ uint64_t d_val;
+};
+
+struct elf64_rela {
+ uint64_t r_offset;
+ uint64_t r_info;
+#define ELF64_R_TYPE(info) ((info) & 0xffffffffu)
+ int64_t r_addend;
+};
+
+/* relocs we support */
+#define R_PPC64_RELATIVE 22
+
+/* 32-bit ELF header */
+struct elf32_hdr {
+ uint32_t ei_ident;
+ uint8_t ei_class;
+ uint8_t ei_data;
+ uint8_t ei_version;
+ uint8_t ei_pad[9];
+ uint16_t e_type;
+ uint16_t e_machine;
+ uint32_t e_version;
+ uint32_t e_entry;
+ uint32_t e_phoff;
+ uint32_t e_shoff;
+ uint32_t e_flags;
+ uint16_t e_ehsize;
+ uint16_t e_phentsize;
+ uint16_t e_phnum;
+ uint16_t e_shentsize;
+ uint16_t e_shnum;
+ uint16_t e_shstrndx;
+};
+
+/* 32-bit ELF program header*/
+struct elf32_phdr {
+ uint32_t p_type;
+ uint32_t p_offset;
+ uint32_t p_vaddr;
+ uint32_t p_paddr;
+ uint32_t p_filesz;
+ uint32_t p_memsz;
+ uint32_t p_flags;
+ uint32_t p_align;
+};
+
+
+#endif /* __ELF_H */
diff --git a/include/fsi-master.h b/include/fsi-master.h
new file mode 100644
index 0000000..e727214
--- /dev/null
+++ b/include/fsi-master.h
@@ -0,0 +1,36 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __FSI_MASTER_H
+#define __FSI_MASTER_H
+
+/*
+ * Definition of the MFSI masters
+ */
+#define MFSI_cMFSI0 0
+#define MFSI_cMFSI1 1
+#define MFSI_hMFSI0 2
+
+extern int64_t mfsi_read(uint32_t chip, uint32_t mfsi, uint32_t port,
+ uint32_t fsi_addr, uint32_t *data);
+
+extern int64_t mfsi_write(uint32_t chip, uint32_t mfsi, uint32_t port,
+ uint32_t fsi_addr, uint32_t data);
+
+extern void mfsi_init(void);
+
+#endif /* __FSI_MASTER_H */
+
diff --git a/include/fsp-elog.h b/include/fsp-elog.h
new file mode 100644
index 0000000..34913c5
--- /dev/null
+++ b/include/fsp-elog.h
@@ -0,0 +1,325 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <opal.h>
+#ifndef __ELOG_H
+#define __ELOG_H
+
+#define ELOG_TYPE_PEL 0
+#define MAX_RETRIES 3
+
+/* Component IDs */
+/* In PEL error log format, Creator ID is hypervisor
+ * But we can have various component ID to distinguish
+ * which component in hypervisor is reporting the error
+ * This is 2 bytes long,
+ * first byte corresponds to Component IDs
+ * Second byte is reserved for the Reason code.
+ * Component ID is mapped to readable 4-digit ascii
+ * character name in FSP and displayed.
+ */
+/* SAPPHIRE components */
+#define OPAL_CODEUPDATE 0x1000
+#define OPAL_CONSOLE 0x2000
+#define OPAL_CEC 0x3000
+#define OPAL_CHIP 0x4000
+#define OPAL_ELOG 0x5000
+#define OPAL_NVRAM 0x6000
+#define OPAL_RTC 0x7000
+#define OPAL_SURVEILLANCE 0x8000
+#define OPAL_SYSPARAM 0x9000
+#define OPAL_LPC 0xa000
+#define OPAL_UART 0xb000
+#define OPAL_OCC 0xc000
+#define OPAL_OP_PANEL 0xd000
+#define OPAL_PHB3 0xe000
+#define OPAL_PSI 0xf000
+#define OPAL_VPD 0x1000
+#define OPAL_XSCOM 0x1100
+#define OPAL_PCI 0x1200
+#define OPAL_MISC 0x1300
+#define OPAL_ATTN 0x1400
+#define OPAL_MEM_ERR 0x1500
+#define OPAL_CENTAUR 0x1600
+#define OPAL_MFSI 0x1700
+#define OPAL_DUMP 0x1800
+#define OPAL_LED 0x1900
+#define OPAL_SENSOR 0x2000
+#define OPAL_SLW 0x2100
+#define OPAL_FSP 0x2200
+
+enum opal_reasoncode {
+/* code update */
+ OPAL_RC_CU_FLASH = OPAL_CODEUPDATE | 0x10,
+ OPAL_RC_CU_INIT = OPAL_CODEUPDATE | 0x11,
+ OPAL_RC_CU_SG_LIST = OPAL_CODEUPDATE | 0x12,
+ OPAL_RC_CU_COMMIT = OPAL_CODEUPDATE | 0x13,
+ OPAL_RC_CU_MSG = OPAL_CODEUPDATE | 0x14,
+ OPAL_RC_CU_NOTIFY = OPAL_CODEUPDATE | 0x15,
+ OPAL_RC_CU_MARKER_LID = OPAL_CODEUPDATE | 0x16,
+/* NVRAM */
+ OPAL_RC_NVRAM_INIT = OPAL_NVRAM | 0x10,
+ OPAL_RC_NVRAM_OPEN = OPAL_NVRAM | 0x11,
+ OPAL_RC_NVRAM_SIZE = OPAL_NVRAM | 0x12,
+ OPAL_RC_NVRAM_WRITE = OPAL_NVRAM | 0x13,
+ OPAL_RC_NVRAM_READ = OPAL_NVRAM | 0x14,
+/* CENTAUR */
+ OPAL_RC_CENTAUR_INIT = OPAL_CENTAUR | 0x10,
+ OPAL_RC_CENTAUR_RW_ERR = OPAL_CENTAUR | 0x11,
+/* MFSI */
+ OPAL_RC_MFSI_RW_ERR = OPAL_MFSI | 0x10,
+/* UART */
+ OPAL_RC_UART_INIT = OPAL_UART | 0x10,
+/* OCC */
+ OPAL_RC_OCC_RESET = OPAL_OCC | 0x10,
+ OPAL_RC_OCC_LOAD = OPAL_OCC | 0x11,
+ OPAL_RC_OCC_PSTATE_INIT = OPAL_OCC | 0x12,
+/* RTC */
+ OPAL_RC_RTC_READ = OPAL_RTC | 0x10,
+ OPAL_RC_RTC_TOD = OPAL_RTC | 0x11,
+/* SURVEILLANCE */
+ OPAL_RC_SURVE_INIT = OPAL_SURVEILLANCE | 0x10,
+ OPAL_RC_SURVE_STATUS = OPAL_SURVEILLANCE | 0x11,
+/* SYSPARAM */
+ OPAL_RC_SYSPARM_INIT = OPAL_SYSPARAM | 0x10,
+ OPAL_RC_SYSPARM_MSG = OPAL_SYSPARAM | 0x11,
+/* LPC */
+ OPAL_RC_LPC_READ = OPAL_LPC | 0x10,
+ OPAL_RC_LPC_WRITE = OPAL_LPC | 0x11,
+/* OP_PANEL */
+ OPAL_RC_PANEL_WRITE = OPAL_OP_PANEL | 0x10,
+/* PSI */
+ OPAL_RC_PSI_INIT = OPAL_PSI | 0x10,
+ OPAL_RC_PSI_IRQ_RESET = OPAL_PSI | 0x11,
+/* XSCOM */
+ OPAL_RC_XSCOM_RW = OPAL_XSCOM | 0x10,
+ OPAL_RC_XSCOM_INDIRECT_RW = OPAL_XSCOM | 0x11,
+ OPAL_RC_XSCOM_RESET = OPAL_XSCOM | 0x12,
+/* PCI */
+ OPAL_RC_PCI_INIT_SLOT = OPAL_PCI | 0x10,
+ OPAL_RC_PCI_ADD_SLOT = OPAL_PCI | 0x11,
+ OPAL_RC_PCI_SCAN = OPAL_PCI | 0x12,
+ OPAL_RC_PCI_RESET_PHB = OPAL_PCI | 0x10,
+/* ATTN */
+ OPAL_RC_ATTN = OPAL_ATTN | 0x10,
+/* MEM_ERR */
+ OPAL_RC_MEM_ERR_RES = OPAL_MEM_ERR | 0x10,
+ OPAL_RC_MEM_ERR_DEALLOC = OPAL_MEM_ERR | 0x11,
+/* DUMP */
+ OPAL_RC_DUMP_INIT = OPAL_DUMP | 0x10,
+ OPAL_RC_DUMP_LIST = OPAL_DUMP | 0x11,
+ OPAL_RC_DUMP_ACK = OPAL_DUMP | 0x12,
+ OPAL_RC_DUMP_MDST_INIT = OPAL_DUMP | 0x13,
+ OPAL_RC_DUMP_MDST_UPDATE = OPAL_DUMP | 0x14,
+/* LED */
+ OPAL_RC_LED_SPCN = OPAL_LED | 0x10,
+ OPAL_RC_LED_BUFF = OPAL_LED | 0x11,
+ OPAL_RC_LED_LC = OPAL_LED | 0x12,
+ OPAL_RC_LED_STATE = OPAL_LED | 0x13,
+ OPAL_RC_LED_SUPPORT = OPAL_LED | 0x14,
+/* SENSOR */
+ OPAL_RC_SENSOR_INIT = OPAL_SENSOR | 0x10,
+ OPAL_RC_SENSOR_READ = OPAL_SENSOR | 0x11,
+ OPAL_RC_SENSOR_ASYNC_COMPLETE
+ = OPAL_SENSOR | 0x12,
+/* SLW */
+ OPAL_RC_SLW_INIT = OPAL_SLW | 0x10,
+ OPAL_RC_SLW_SET = OPAL_SLW | 0x11,
+ OPAL_RC_SLW_GET = OPAL_SLW | 0x12,
+ OPAL_RC_SLW_REG = OPAL_SLW | 0x13,
+/* FSP */
+ OPAL_RC_FSP_POLL_TIMEOUT
+ = OPAL_FSP | 0x10,
+};
+
+/* Data Structures for PEL data. */
+
+#define PRIVATE_HEADER_SECTION_SIZE 48
+#define USER_HEADER_SECTION_SIZE 24
+#define SRC_SECTION_SIZE 80
+#define SRC_SUBSECTION_SIZE 4
+#define SRC_LENGTH 72
+#define OPAL_MAX_SRC_BYTES 32
+#define EXTENDED_HEADER_SECTION_SIZE 76
+#define MTMS_SECTION_SIZE 28
+#define IO_EVENT_SECTION_SIZE 16
+
+#define OPAL_ELOG_VERSION 1
+#define OPAL_ELOG_SST 0
+#define OPAL_SRC_MAX_WORD_COUNT 8
+
+#define OPAL_SRC_FORMAT 0x80
+#define OPAL_FAILING_SUBSYSTEM 0x82
+
+#define OPAL_SYS_MODEL_LEN 8
+#define OPAL_SYS_SERIAL_LEN 12
+#define OPAL_VER_LEN 16
+#define OPAL_SYMPID_LEN 80
+#define OPAL_RC_NONE 0
+
+#define OPAL_IO_MAX_RPC_DATA 216
+#define OPAL_SRC_SEC_VER 0x02
+#define OPAL_EXT_HRD_VER 0x01
+
+/* Error log reporting action */
+#define ERRL_ACTION_REPORT 0x2000
+#define ERRL_ACTION_NONE 0x0000
+
+enum elogSectionId {
+ ELOG_SID_PRIVATE_HEADER = 0x5048, /* PH */
+ ELOG_SID_USER_HEADER = 0x5548, /* UH */
+ ELOG_SID_EXTENDED_HEADER = 0x4548, /* EH */
+ ELOG_SID_PRIMARY_SRC = 0x5053, /* PS */
+ ELOG_SID_MACHINE_TYPE = 0x4D54, /* MT */
+ ELOG_SID_SECONDARY_SRC = 0x5353, /* SS */
+ ELOG_SID_CALL_HOME = 0x4348, /* CH */
+ ELOG_SID_DUMP_LOCATOR = 0x4448, /* DH */
+ ELOG_SID_SOFTWARE_ERROR = 0x5357, /* SW */
+ ELOG_SID_PARTITION = 0x4C50, /* LP */
+ ELOG_SID_LOGICAL_RESOURCE = 0x4C52, /* LR */
+ ELOG_SID_HMC_ID = 0x484D, /* HM */
+ ELOG_SID_EPOW = 0x4550, /* EP */
+ ELOG_SID_IO_EVENT = 0x4945, /* IE */
+ ELOG_SID_MFG_INFORMATION = 0x4D49, /* MI */
+ ELOG_SID_USER_DEFINED = 0x5544 /* UD */
+};
+
+struct opal_v6_header {
+ enum elogSectionId id:16; /* section id */
+ uint16_t length; /* section length */
+ uint8_t version; /* section version */
+ uint8_t subtype; /* section sub-type id */
+ uint16_t component_id; /* component id of section creator */
+};
+
+/* opal_srctype */
+#define OPAL_SRC_TYPE_ERROR 0xBB
+
+#define OPAL_CID_SAPPHIRE 'K' /* creator ID for sapphire log */
+#define OPAL_CID_POWERNV 'P' /* creator ID for powernv log */
+
+/* Origin of error, elog_origin */
+#define ORG_SAPPHIRE 1
+#define ORG_POWERNV 2
+
+/*struct opal_private head section_ */
+struct opal_private_header_section {
+
+ struct opal_v6_header v6header;
+ uint32_t create_date;
+ uint32_t create_time;
+ uint32_t commit_date;
+ uint32_t commit_time;
+
+ uint32_t creator_id:8; /* subsystem component id */
+ uint32_t reserved_0:16;
+ uint32_t section_count:8; /* number of sections in log */
+ uint32_t reserved_1;
+ uint32_t creator_subid_hi;
+ uint32_t creator_subid_lo;
+ uint32_t plid; /* platform log id */
+ uint32_t log_entry_id; /* Unique log entry id */
+};
+
+/* opal user header section */
+struct opal_user_header_section {
+
+ struct opal_v6_header v6header;
+
+ uint8_t subsystem_id; /* subsystem id */
+ uint8_t event_scope;
+ uint8_t event_severity;
+ uint8_t event_type; /* error/event severity */
+
+ uint32_t reserved_0;
+ uint16_t reserved_1;
+ uint16_t action_flags; /* error action code */
+ uint32_t reserved_2;
+};
+
+struct opal_src_section {
+ struct opal_v6_header v6header;
+ uint8_t version;
+ uint8_t flags;
+ uint8_t reserved_0;
+ uint8_t wordcount;
+ uint16_t reserved_1;
+ uint16_t srclength;
+ uint32_t hexwords[OPAL_SRC_MAX_WORD_COUNT];
+ char srcstring[OPAL_MAX_SRC_BYTES];
+};
+
+struct opal_extended_header_section {
+ struct opal_v6_header v6header;
+ char model[OPAL_SYS_MODEL_LEN];
+ char serial_no[OPAL_SYS_SERIAL_LEN];
+ char opal_release_version[OPAL_VER_LEN];
+ char opal_subsys_version[OPAL_VER_LEN];
+ uint16_t reserved_0;
+ uint32_t extended_header_date;
+ uint32_t extended_header_time;
+ uint16_t reserved_1;
+ uint8_t reserved_2;
+ uint8_t opal_symid_len;
+ char opalsymid[OPAL_SYMPID_LEN];
+};
+
+/* opal MTMS section */
+struct opal_mtms_section {
+ struct opal_v6_header v6header;
+ char model[OPAL_SYS_MODEL_LEN];
+ char serial_no[OPAL_SYS_SERIAL_LEN];
+};
+
+/* User defined section */
+struct opal_user_section {
+ struct opal_v6_header v6header;
+ char dump[1];
+};
+
+struct opal_err_info {
+ uint32_t reason_code;
+ uint8_t err_type;
+ uint16_t cmp_id;
+ uint8_t subsystem;
+ uint8_t sev;
+ uint8_t event_subtype;
+ void (*call_out)(struct opal_errorlog *buf, void *data, uint16_t size);
+};
+
+#define DEFINE_LOG_ENTRY(reason, type, id, subsys, \
+severity, subtype, callout_func) struct opal_err_info err_##reason = \
+{ .reason_code = reason, .err_type = type, .cmp_id = id, \
+.subsystem = subsys, .sev = severity, .event_subtype = subtype, \
+.call_out = callout_func }
+
+#define e_info(reason_code) err_##reason_code
+
+struct opal_errorlog *opal_elog_create(struct opal_err_info *e_info);
+
+int opal_elog_update_user_dump(struct opal_errorlog *buf, unsigned char *data,
+ uint32_t tag, uint16_t size);
+
+int elog_fsp_commit(struct opal_errorlog *buf);
+
+/* This is wrapper around the error log function, which creates
+ * and commits the error to FSP.
+ * Used for simple error logging
+ */
+void log_simple_error(struct opal_err_info *e_info, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+void log_error(struct opal_err_info *e_info, void *data, uint16_t size,
+ const char *fmt, ...) __attribute__ ((format (printf, 4, 5)));
+
+#endif /* __ELOG_H */
diff --git a/include/fsp-leds.h b/include/fsp-leds.h
new file mode 100644
index 0000000..66cbe8a
--- /dev/null
+++ b/include/fsp-leds.h
@@ -0,0 +1,135 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ */
+
+
+/*
+ * SPCN based LED location code and other information
+ */
+
+#ifndef __FSP_LEDS_H
+#define __FSP_LEDS_H
+
+/* Supported FSP response codes */
+#define FSP_IND_NOT_IMPLMNTD 0x00 /* Indicator not implemented */
+#define FSP_IND_IMPLMNTD 0x04 /* Indicator implemented */
+#define FSP_IND_IMPL_UNKNOWN 0x08 /* Implemtation unknown */
+#define FSP_IND_INACTIVE 0x00 /* Indicator not active */
+#define FSP_IND_IDENTIFY_ACTV 0x01 /* Identify state active */
+#define FSP_IND_FAULT_ACTV 0x02 /* Fault state active */
+#define FSP_IND_STATE_UNKNOWN 0xff /* Indicator state unknown */
+#define FSP_RSRC_NOT_PRESENT 0x00 /* Resource not present */
+#define FSP_RSRC_PRESENT 0x40 /* Resource present */
+#define FSP_RSRC_PRSNC_UNKNOWN 0x80 /* Resource presence unknown */
+
+/* LED exclussive bits */
+#define FSP_LED_EXCL_FAULT 1UL << 0
+#define FSP_LED_EXCL_IDENTIFY 1UL << 1
+
+/* SPCN set LED */
+struct spcn_led_data {
+ u8 lc_len;
+ u16 state;
+ char lc_code[LOC_CODE_SIZE];
+};
+
+/* LED data */
+struct fsp_led_data {
+ u16 rid; /* Resource ID */
+ u8 lc_len; /* Location code len */
+ char loc_code[LOC_CODE_SIZE];
+ u16 parms; /* Parameters */
+ u16 status; /* Status */
+ u16 ckpt_status; /* Checkpointed status */
+ u16 excl_bit; /* Exclussive LED bit */
+ struct list_node link;
+};
+
+/* FSP location code request */
+struct fsp_loc_code_req {
+ u16 len;
+ u16 req_type;
+ u8 raw_len;
+ u8 lc_sz;
+ char loc_code[LOC_CODE_SIZE];
+};
+
+/* FSP location code data */
+struct fsp_loc_code_data {
+ u16 size;
+ u32 ccin;
+ u8 status;
+ u8 ind_state;
+ u8 raw_len;
+ u8 fld_sz;
+
+ /* The size below must include the padding to
+ * make the whole structure aligned to a
+ * multiple of 4 bytes
+ */
+ char loc_code[LOC_CODE_SIZE + 2]; /* 82 */
+
+ /* We need to pack the structure otherwise the
+ * compiler adds additional alignment to make
+ * it 8 bytes aligned
+ */
+} __packed;
+
+/* Get indicator state request */
+struct fsp_get_ind_state_req {
+ u16 size;
+ u8 lc_len;
+ u8 fld_sz;
+ char loc_code[LOC_CODE_SIZE];
+};
+
+/* Set indicator state request */
+struct fsp_set_ind_state_req {
+ u16 size;
+ u16 req_type;
+ u8 reserved[3];
+ u8 ind_state;
+ u8 lc_len;
+ u8 fld_sz;
+ char loc_code[LOC_CODE_SIZE];
+};
+
+/* LED commands and state */
+#define LED_COMMAND_FAULT 1
+#define LED_COMMAND_IDENTIFY 0
+#define LED_STATE_ON 1
+#define LED_STATE_OFF 0
+
+/* FSP get loc-code list command request type */
+#define GET_LC_CMPLT_SYS 0x8000
+#define GET_LC_ENCLOSURES 0x4000
+#define GET_LC_ENCL_DESCENDANTS 0x2000
+#define GET_LC_SINGLE_LOC_CODE 0x0100
+
+/* FSP set indicator command request type */
+#define SET_IND_ENCLOSURE 0x4000
+#define SET_IND_SINGLE_LOC_CODE 0x0001
+
+/* Response buffer */
+#define OUTBUF_HEADER_SIZE 8
+
+/* LED miscellaneous */
+#define LOC_CODE_LEN 1
+#define LED_CONTROL_LEN 2
+#define FSP_LC_STRUCT_FIXED_SZ 0x0a
+
+#endif
diff --git a/include/fsp-mdst-table.h b/include/fsp-mdst-table.h
new file mode 100644
index 0000000..ae2ef12
--- /dev/null
+++ b/include/fsp-mdst-table.h
@@ -0,0 +1,37 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __FSPMDST_H
+#define __FSPMDST_H
+
+/* Dump section type */
+#define DUMP_SECTION_CONSOLE 0x01
+#define DUMP_SECTION_HBRT_LOG 0x02
+
+/*
+ * Sapphire Memory Dump Source Table
+ *
+ * Format of this table is same as Memory Dump Source Table (MDST)
+ * defined in HDAT spec.
+ */
+struct dump_mdst_table {
+ uint64_t addr;
+ uint32_t type; /* DUMP_SECTION_* */
+ uint32_t size;
+};
+
+#endif /* __FSPMDST_H */
diff --git a/include/fsp-sysparam.h b/include/fsp-sysparam.h
new file mode 100644
index 0000000..1a7a472
--- /dev/null
+++ b/include/fsp-sysparam.h
@@ -0,0 +1,57 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __FSP_SYSPARAM_H
+#define __FSP_SYSPARAM_H
+
+/* System parameter numbers used in the protocol
+ *
+ * these are the only ones we care about right now
+ */
+#define SYS_PARAM_SURV 0xf0000001
+#define SYS_PARAM_HMC_MANAGED 0xf0000003
+#define SYS_PARAM_FLASH_POLICY 0xf0000012
+#define SYS_PARAM_NEED_HMC 0xf0000016
+#define SYS_PARAM_FW_LICENSE 0xf000001d
+#define SYS_PARAM_WWPN 0xf0000023
+#define SYS_PARAM_DEF_BOOT_DEV 0xf0000024
+#define SYS_PARAM_NEXT_BOOT_DEV 0xf0000025
+
+
+
+/* Completion for a sysparam call. err_len is either a negative error
+ * code or the positive length of the returned data
+ */
+typedef void (*sysparam_compl_t)(uint32_t param_id, int err_len, void *data);
+
+
+/* Send a sysparam query request. Operation can be synchronous or
+ * asynchronous:
+ *
+ * - synchronous (async_complete is NULL), the result code is either
+ * a negative error code or a positive returned length.
+ *
+ * - asynchronous (async_complete non NULL). The result code is 0 for
+ * successfully queued request or an error for an immediate error.
+ * A successfully queued request will complete via the completion
+ * callback defined above
+ */
+int fsp_get_sys_param(uint32_t param_id, void *buffer, uint32_t length,
+ sysparam_compl_t async_complete, void *comp_data);
+
+
+void fsp_sysparam_init(void);
+
+#endif /* __FSP_SYSPARAM_H */
diff --git a/include/fsp.h b/include/fsp.h
new file mode 100644
index 0000000..b6f6f0e
--- /dev/null
+++ b/include/fsp.h
@@ -0,0 +1,755 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/*
+ * IBM System P FSP (Flexible Service Processor)
+ */
+#ifndef __FSP_H
+#define __FSP_H
+
+#include <skiboot.h>
+#include <psi.h>
+
+/* Current max number of FSPs
+ * one primary and one secondary is all we support
+ */
+#define FSP_MAX 2
+
+/* Command protocol.
+ *
+ * Commands have a byte class and a byte subcommand. With the exception
+ * of some HMC related commands (class 0xe0) which we don't support,
+ * only one outstanding command is allowed for a given class.
+ *
+ * Note: 0xCE and 0xCF fall into the same class, ie, only one of them can
+ * be outstanding.
+ *
+ * A command is outstanding until it has been acknowledged. This doesn't
+ * imply a response, the response can come later.
+ */
+
+/* Protocol status error codes used by the protocol */
+#define FSP_STATUS_SUCCESS 0x00 /* Command successful */
+#define FSP_STATUS_MORE_DATA 0x02 /* Success, EOF not reached */
+#define FSP_STATUS_DATA_INLINE 0x11 /* Data inline in mbox */
+#define FSP_STATUS_INVALID_SUBCMD 0x20
+#define FSP_STATUS_INVALID_MOD 0x21
+#define FSP_STATUS_INVALID_DATA 0x22
+#define FSP_STATUS_INVALID_DPOSTATE 0x23
+#define FSP_STATUS_DMA_ERROR 0x24
+#define FSP_STATUS_INVALID_CMD 0x2c
+#define FSP_STATUS_SEQ_ERROR 0x2d
+#define FSP_STATUS_BAD_STATE 0x2e
+#define FSP_STATUS_NOT_SUPPORTED 0x2f
+#define FSP_STATUS_FILE_TOO_LARGE 0x43
+#define FSP_STATUS_FLASH_INPROGRESS 0x61
+#define FSP_STATUS_FLASH_NOPROGRESS 0x62
+#define FSP_STATUS_FLASH_INVALID_SIDE 0x63
+#define FSP_STATUS_GENERIC_ERROR 0xfe
+#define FSP_STATUS_EOF_ERROR 0x02
+#define FSP_STATUS_DMA_ERROR 0x24
+#define FSP_STATUS_BUSY 0x3e
+#define FSP_STATUS_FLASH_BUSY 0x3f
+#define FSP_STATUS_INVALID_SUBID 0x41
+#define FSP_STATUS_LENGTH_ERROR 0x42
+#define FSP_STAUS_INVALID_HMC_ID 0x51
+#define FSP_STATUS_SPCN_ERROR 0xA8 /* SPCN error */
+#define FSP_STATUS_INVALID_LC 0xC0 /* Invalid location code */
+
+/*
+ * FSP registers
+ *
+ * All of the below register definitions come from the FSP0 "Black Widow" spec
+ * They are the same for FSP1 except they are presented big-endian vs
+ * little-endian for FSP0 -- which used PCI
+ * all regs are 4 bytes wide, and we read the larger data areas in 4 byte
+ * granularity as well
+ *
+ * there are actually two defined sets of MBX registers
+ * MBX2 can't generate interrupts to the host and only MBX1 is currently
+ * used by firmware running on the FSP, so we're mostly ignoring MBX2
+ */
+
+/* Device Reset Control Register */
+#define FSP_DRCR_REG 0x00
+#define FSP_DRCR_CLR_REG 0x04
+
+/* Bit masks for DRCR */
+#define FSP_DRCR_CMD_VALID PPC_BIT32(16)
+#define FSP_DRCR_TERMINATE PPC_BIT32(17)
+#define FSP_DRCR_PREP_FOR_RESET PPC_BIT32(23)
+#define FSP_DRCR_CLEAR_DISR PPC_BIT32(30)
+
+/* DRCR commands need the CMD_VALID bit set */
+#define FSP_PREP_FOR_RESET_CMD (FSP_DRCR_CMD_VALID | \
+ FSP_DRCR_PREP_FOR_RESET)
+#define FSP_DRCR_ACK_MASK (0xff << 8)
+
+/* Device Immediate Status Register */
+#define FSP_DISR_REG 0x08
+#define FSP_DISR_CLR_REG 0x0C
+
+/* Bit masks for DISR */
+#define FSP_DISR_FSP_RR_COMPLETE PPC_BIT32(22)
+#define FSP_DISR_RUNTIME_STATE_SYNCD PPC_BIT32(24)
+#define FSP_DISR_DBG_IN_PROGRESS PPC_BIT32(25)
+#define FSP_DISR_FSP_IN_RR PPC_BIT32(26)
+#define FSP_DISR_FSP_REBOOT_IN_PROGRESS PPC_BIT32(27)
+#define FSP_DISR_CRIT_OP_IN_PROGRESS PPC_BIT32(28)
+#define FSP_DISR_STATUS_ACK_RXD PPC_BIT32(31)
+
+/* The host version of the control register shares bits with the FSP's
+ * control reg. Those bits are defined such that one side can set
+ * a bit and the other side can clear it
+ */
+#define FSP_MBX1_HCTL_REG 0x080 /* AKA DSCR1 */
+#define FSP_MBX1_FCTL_REG 0x090
+#define FSP_MBX2_HCTL_REG 0x0a0 /* AKA DSCR2 */
+#define FSP_MBX2_FCTL_REG 0x0b0
+
+/* Bits in the control reg */
+#define FSP_MBX_CTL_PTS (1 << 31)
+#define FSP_MBX_CTL_ABORT (1 << 30)
+#define FSP_MBX_CTL_SPPEND (1 << 29)
+#define FSP_MBX_CTL_HPEND (1 << 28)
+#define FSP_MBX_CTL_XDN (1 << 26)
+#define FSP_MBX_CTL_XUP (1 << 25)
+#define FSP_MBX_CTL_HCHOST_MASK (0xf << 20)
+#define FSP_MBX_CTL_HCHOST_SHIFT 20
+#define FSP_MBX_CTL_DCHOST_MASK (0xff << 12)
+#define FSP_MBX_CTL_DCHOST_SHIFT 12
+#define FSP_MBX_CTL_HCSP_MASK (0xf << 8)
+#define FSP_MBX_CTL_HCSP_SHIFT 8
+#define FSP_MBX_CTL_DCSP_MASK (0xff)
+#define FSP_MBX_CTL_DCSP_SHIFT 0
+
+/* Three header registers owned by the host */
+#define FSP_MBX1_HHDR0_REG 0x84
+#define FSP_MBX1_HHDR1_REG 0x88
+#define FSP_MBX1_HHDR2_REG 0x8C
+#define FSP_MBX2_HHDR0_REG 0xa4
+#define FSP_MBX2_HHDR1_REG 0xa8
+#define FSP_MBX2_HHDR2_REG 0xaC
+
+/* SP Doorbell Error Status register */
+#define FSP_SDES_REG 0xc0
+
+/* Host Doorbell Error Status register */
+#define FSP_HDES_REG 0xc4
+
+/* Bit definitions for both SDES and HDES
+ *
+ * Notes:
+ *
+ * - CLR: is written to clear the status and always reads
+ * as 0. It can be used to detect an error state (a HB
+ * freeze will return all 1's)
+ * - ILLEGAL: illegal operation such as host trying to write
+ * to an FSP only register etc...
+ * - WFULL: set if host tried to write to the SP doorbell while
+ * the pending bit is still set
+ * - REMPTY: tried to read while host pending bit not set
+ * - PAR: SP RAM parity error
+ */
+#define FSP_DBERRSTAT_ILLEGAL1 (1 << 27)
+#define FSP_DBERRSTAT_WFULL1 (1 << 26)
+#define FSP_DBERRSTAT_REMPTY1 (1 << 25)
+#define FSP_DBERRSTAT_PAR1 (1 << 24)
+#define FSP_DBERRSTAT_CLR1 (1 << 16)
+#define FSP_DBERRSTAT_ILLEGAL2 (1 << 11)
+#define FSP_DBERRSTAT_WFULL2 (1 << 10)
+#define FSP_DBERRSTAT_REMPTY2 (1 << 9)
+#define FSP_DBERRSTAT_PAR2 (1 << 8)
+#define FSP_DBERRSTAT_CLR2 (1 << 0)
+
+/* Host Doorbell Interrupt Register and mask
+ *
+ * Note that while HDIR has bits for MBX2, only
+ * MBX1 can actually generate interrupts. Thus only the
+ * MBX1 bits are implemented in the mask register.
+ */
+#define FSP_HDIR_REG 0xc8
+#define FSP_HDIM_SET_REG 0xcc
+#define FSP_HDIM_CLR_REG 0xd0
+#define FSP_DBIRQ_ERROR2 (1 << 10)
+#define FSP_DBIRQ_XUP2 (1 << 9)
+#define FSP_DBIRQ_HPEND2 (1 << 8)
+#define FSP_DBIRQ_ERROR1 (1 << 2)
+#define FSP_DBIRQ_XUP1 (1 << 1)
+#define FSP_DBIRQ_HPEND1 (1 << 0)
+#define FSP_DBIRQ_MBOX1 (FSP_DBIRQ_ERROR1 | FSP_DBIRQ_XUP1 | \
+ FSP_DBIRQ_HPEND1)
+#define FSP_DBIRQ_MBOX2 (FSP_DBIRQ_ERROR2 | FSP_DBIRQ_XUP2 | \
+ FSP_DBIRQ_HPEND2)
+#define FSP_DBIRQ_ALL (FSP_DBIRQ_MBOX1 | FSP_DBIRQ_MBOX2)
+
+/* Doorbell Interrupt Register (FSP internal interrupt latch
+ * read-only on host side
+ */
+#define FSP_PDIR_REG 0xd4
+/* And associated mask */
+#define FSP_PDIM_SET_REG 0xd8
+#define FSP_PDIM_CLR_REG 0xdc
+
+/* Bits for the above */
+#define FSP_PDIRQ_ABORT2 (1 << 7)
+#define FSP_PDIRQ_ABORT1 (1 << 6)
+#define FSP_PDIRQ_ERROR2 (1 << 5)
+#define FSP_PDIRQ_ERROR1 (1 << 4)
+#define FSP_PDIRQ_XDN2 (1 << 3)
+#define FSP_PDIRQ_XDN1 (1 << 2)
+#define FSP_PDIRQ_SPPEND2 (1 << 1)
+#define FSP_PDIRQ_SPPEND1 (1 << 0)
+
+/* FSP owned headers */
+#define FSP_MBX1_FHDR0_REG 0x094
+#define FSP_MBX1_FHDR1_REG 0x098
+#define FSP_MBX1_FHDR2_REG 0x09C
+#define FSP_MBX2_FHDR0_REG 0x0b4
+#define FSP_MBX2_FHDR1_REG 0x0b8
+#define FSP_MBX2_FHDR2_REG 0x0bC
+
+/* Data areas, we can only write to host data, and read from FSP data
+ *
+ * Each area is 0x140 bytes long
+ */
+#define FSP_MBX1_HDATA_AREA 0x100
+#define FSP_MBX1_FDATA_AREA 0x200
+#define FSP_MBX2_HDATA_AREA 0x300
+#define FSP_MBX2_FDATA_AREA 0x400
+
+/* These are scratch registers */
+#define FSP_SCRATCH0_REG 0xe0
+#define FSP_SCRATCH1_REG 0xe4
+#define FSP_SCRATCH2_REG 0xe8
+#define FSP_SCRATCH3_REG 0xec
+
+/* This is what the cmd_sub_mod will have for FSP_MCLASS_RR_EVENT */
+#define FSP_RESET_START 0x1
+#define FSP_RELOAD_COMPLETE 0x2
+
+/*
+ * Message classes
+ */
+
+/* The FSP_MCLASS_RR_EVENT is a special message class that doesn't
+ * participate in mbox event related activities. Its relevant only
+ * for hypervisor internal use. So, handle it specially for command
+ * class extraction too.
+ */
+#define FSP_MCLASS_RR_EVENT 0xaa /* see FSP_R/R defines above */
+#define FSP_MCLASS_FIRST 0xce
+#define FSP_MCLASS_SERVICE 0xce
+#define FSP_MCLASS_IPL 0xcf
+#define FSP_MCLASS_PCTRL_MSG 0xd0
+#define FSP_MCLASS_PCTRL_ABORTS 0xd1
+#define FSP_MCLASS_ERR_LOG 0xd2
+#define FSP_MCLASS_CODE_UPDATE 0xd3
+#define FSP_MCLASS_FETCH_SPDATA 0xd4
+#define FSP_MCLASS_FETCH_HVDATA 0xd5
+#define FSP_MCLASS_NVRAM 0xd6
+#define FSP_MCLASS_MBOX_SURV 0xd7
+#define FSP_MCLASS_RTC 0xd8
+#define FSP_MCLASS_SMART_CHIP 0xd9
+#define FSP_MCLASS_INDICATOR 0xda
+#define FSP_MCLASS_HMC_INTFMSG 0xe0
+#define FSP_MCLASS_HMC_VT 0xe1
+#define FSP_MCLASS_HMC_BUFFERS 0xe2
+#define FSP_MCLASS_SHARK 0xe3
+#define FSP_MCLASS_MEMORY_ERR 0xe4
+#define FSP_MCLASS_CUOD_EVENT 0xe5
+#define FSP_MCLASS_HW_MAINT 0xe6
+#define FSP_MCLASS_VIO 0xe7
+#define FSP_MCLASS_SRC_MSG 0xe8
+#define FSP_MCLASS_DATA_COPY 0xe9
+#define FSP_MCLASS_TONE 0xea
+#define FSP_MCLASS_VIRTUAL_NVRAM 0xeb
+#define FSP_MCLASS_TORRENT 0xec
+#define FSP_MCLASS_NODE_PDOWN 0xed
+#define FSP_MCLASS_DIAG 0xee
+#define FSP_MCLASS_PCIE_LINK_TOPO 0xef
+#define FSP_MCLASS_OCC 0xf0
+#define FSP_MCLASS_LAST 0xf0
+
+/*
+ * Commands are provided in rxxyyzz form where:
+ *
+ * - r is 0: no response or 1: response expected
+ * - xx is class
+ * - yy is subcommand
+ * - zz is mod
+ *
+ * WARNING: We only set the r bit for HV->FSP commands
+ * long run, we want to remove use of that bit
+ * and instead have a table of all commands in
+ * the FSP driver indicating which ones take a
+ * response...
+ */
+
+/*
+ * Class 0xCF
+ */
+#define FSP_CMD_OPL 0x0cf7100 /* HV->FSP: Operational Load Compl. */
+#define FSP_CMD_HV_STATE_CHG 0x0cf0200 /* FSP->HV: Request HV state change */
+#define FSP_RSP_HV_STATE_CHG 0x0cf8200
+#define FSP_CMD_SP_NEW_ROLE 0x0cf0700 /* FSP->HV: FSP assuming a new role */
+#define FSP_RSP_SP_NEW_ROLE 0x0cf8700
+#define FSP_CMD_SP_RELOAD_COMP 0x0cf0102 /* FSP->HV: FSP reload complete */
+
+
+/*
+ * Class 0xCE
+ */
+#define FSP_CMD_ACK_DUMP 0x1ce0200 /* HV->FSP: Dump ack */
+#define FSP_CMD_HYP_MDST_TABLE 0x1ce2600 /* HV->FSP: Sapphire MDST table */
+#define FSP_CMD_CONTINUE_IPL 0x0ce7000 /* FSP->HV: HV has control */
+#define FSP_RSP_SYS_DUMP_OLD 0x0ce7800 /* FSP->HV: Sys Dump Available */
+#define FSP_RSP_SYS_DUMP 0x0ce7802 /* FSP->HV: Sys Dump Available */
+#define FSP_RSP_RES_DUMP 0x0ce7807 /* FSP->HV: Resource Dump Available */
+#define FSP_CMD_CONTINUE_ACK 0x0ce5700 /* HV->FSP: HV acks CONTINUE IPL */
+#define FSP_CMD_HV_FUNCTNAL 0x1ce5707 /* HV->FSP: Set HV functional state */
+#define FSP_CMD_FSP_FUNCTNAL 0x0ce5708 /* FSP->HV: FSP functional state */
+#define FSP_CMD_HV_QUERY_CAPS 0x1ce0400 /* HV->FSP: Query capabilities */
+#define FSP_RSP_HV_QUERY_CAPS 0x1ce8400
+#define FSP_CMD_SP_QUERY_CAPS 0x0ce0501 /* FSP->HV */
+#define FSP_RSP_SP_QUERY_CAPS 0x0ce8500
+#define FSP_CMD_QUERY_SPARM 0x1ce1200 /* HV->FSP: System parameter query */
+#define FSP_RSP_QUERY_SPARM 0x0ce9200 /* FSP->HV: System parameter resp */
+#define FSP_CMD_SET_SPARM_1 0x1ce1301 /* HV->FSP: Set system parameter */
+#define FSP_CMD_SET_SPARM_2 0x1ce1302 /* HV->FSP: Set system parameter TCE */
+#define FSP_RSP_SET_SPARM 0x0ce9300 /* FSP->HV: Set system parameter resp */
+#define FSP_CMD_SP_SPARM_UPD_0 0x0ce1600 /* FSP->HV: Sysparm updated no data */
+#define FSP_CMD_SP_SPARM_UPD_1 0x0ce1601 /* FSP->HV: Sysparm updated data */
+#define FSP_CMD_POWERDOWN_NORM 0x1ce4d00 /* HV->FSP: Normal power down */
+#define FSP_CMD_POWERDOWN_QUICK 0x1ce4d01 /* HV->FSP: Quick power down */
+#define FSP_CMD_POWERDOWN_PCIRS 0x1ce4d02 /* HV->FSP: PCI cfg reset power dwn */
+#define FSP_CMD_REBOOT 0x1ce4e00 /* HV->FSP: Standard IPL */
+#define FSP_CMD_DEEP_REBOOT 0x1ce4e04 /* HV->FSP: Deep IPL */
+#define FSP_CMD_PANELSTATUS 0x0ce5c00 /* FSP->HV */
+#define FSP_CMD_PANELSTATUS_EX1 0x0ce5c02 /* FSP->HV */
+#define FSP_CMD_PANELSTATUS_EX2 0x0ce5c03 /* FSP->HV */
+#define FSP_CMD_ERRLOG_PHYP_ACK 0x1ce0800 /* HV->FSP */
+#define FSP_RSP_ERRLOG_PHYP_ACK 0x0ce8800 /* FSP->HV */
+#define FSP_CMD_ERRLOG_GET_PLID 0x0ce0900 /* FSP->HV: Get PLID */
+#define FSP_RSP_ERRLOG_GET_PLID 0x0ce8900 /* HV->FSP */
+#define FSP_CMD_GET_IPL_SIDE 0x1ce0600 /* HV->FSP: Get IPL side and speed */
+#define FSP_CMD_SET_IPL_SIDE 0x1ce0780 /* HV->FSP: Set next IPL side */
+#define FSP_CMD_PCI_POWER_CONF 0x1ce1b00 /* HV->FSP: Send PCIe list to FSP */
+
+/*
+ * Class 0xD2
+ */
+#define FSP_CMD_CREATE_ERRLOG 0x1d21000 /* HV->FSP */
+#define FSP_RSP_CREATE_ERRLOG 0x0d29000 /* FSP->HV */
+#define FSP_CMD_ERRLOG_NOTIFICATION 0x0d25a00 /* FSP->HV */
+#define FSP_RSP_ERRLOG_NOTIFICATION 0x0d2da00 /* HV->FSP */
+#define FSP_RSP_ELOG_NOTIFICATION_ERROR 0x1d2dafe /* HV->FSP */
+#define FSP_CMD_FSP_DUMP_INIT 0x1d21200 /* HV->FSP: FSP dump init */
+
+/*
+ * Class 0xD0
+ */
+#define FSP_CMD_SPCN_PASSTHRU 0x1d05400 /* HV->FSP */
+#define FSP_RSP_SPCN_PASSTHRU 0x0d0d400 /* FSP->HV */
+
+/*
+ * Class 0xD3
+ */
+#define FSP_CMD_FLASH_START 0x01d30101 /* HV->FSP: Code update start */
+#define FSP_CMD_FLASH_COMPLETE 0x01d30201 /* HV->FSP: Code update complete */
+#define FSP_CMD_FLASH_ABORT 0x01d302ff /* HV->FSP: Code update complete */
+#define FSP_CMD_FLASH_WRITE 0x01d30300 /* HV->FSP: Write LID */
+#define FSP_CMD_FLASH_DEL 0x01d30500 /* HV->FSP: Delete LID */
+#define FSP_CMD_FLASH_NORMAL 0x01d30401 /* HV->FSP: Commit (T -> P) */
+#define FSP_CMD_FLASH_REMOVE 0x01d30402 /* HV->FSP: Reject (P -> T) */
+#define FSP_CMD_FLASH_SWAP 0x01d30403 /* HV->FSP: Swap */
+#define FSP_CMD_FLASH_OUTC 0x00d30601 /* FSP->HV: Out of band commit */
+#define FSP_CMD_FLASH_OUTR 0x00d30602 /* FSP->HV: Out of band reject */
+#define FSP_CMD_FLASH_OUTS 0x00d30603 /* FSP->HV: Out of band swap */
+#define FSP_CMD_FLASH_OUT_RSP 0x00d38600 /* HV->FSP: Out of band Resp */
+#define FSP_CMD_FLASH_CACHE 0x00d30700 /* FSP->HV: Update LID cache */
+#define FSP_CMD_FLASH_CACHE_RSP 0x00d38700 /* HV->FSP: Update LID cache Resp */
+
+/*
+ * Class 0xD4
+ */
+#define FSP_CMD_FETCH_SP_DATA 0x1d40101 /* HV->FSP: Fetch & DMA data */
+#define FSP_CMD_WRITE_SP_DATA 0x1d40201 /* HV->FSP: Fetch & DMA data */
+
+/* Data set IDs for SP data commands */
+#define FSP_DATASET_SP_DUMP 0x01
+#define FSP_DATASET_HW_DUMP 0x02
+#define FSP_DATASET_ERRLOG 0x03 /* error log entry */
+#define FSP_DATASET_MASTER_LID 0x04
+#define FSP_DATASET_NONSP_LID 0x05
+#define FSP_DATASET_ELID_RDATA 0x06
+#define FSP_DATASET_BLADE_PARM 0x07
+#define FSP_DATASET_LOC_PORTMAP 0x08
+#define FSP_DATASET_SYSIND_CAP 0x09
+#define FSP_DATASET_FSP_RSRCDMP 0x0a
+#define FSP_DATASET_HBRT_BLOB 0x0b
+
+/* Adjustment to get T side LIDs */
+#define ADJUST_T_SIDE_LID_NO 0x8000
+
+/*
+ * Class 0xD5
+ */
+#define FSP_CMD_ALLOC_INBOUND 0x0d50400 /* FSP->HV: Allocate inbound buf. */
+#define FSP_RSP_ALLOC_INBOUND 0x0d58400
+
+/*
+ * Class 0xD7
+ */
+#define FSP_CMD_SURV_HBEAT 0x1d70000 /* ? */
+#define FSP_CMD_SURV_ACK 0x0d78000 /* ? */
+
+/*
+ * Class 0xD8
+ */
+#define FSP_CMD_READ_TOD 0x1d82000 /* HV->FSP */
+#define FSP_CMD_READ_TOD_EXT 0x1d82001 /* HV->FSP */
+#define FSP_CMD_WRITE_TOD 0x1d82100 /* HV->FSP */
+#define FSP_CMD_WRITE_TOD_EXT 0x1d82101 /* HV->FSP */
+
+/*
+ * Class 0xDA
+ */
+#define FSP_CMD_GET_LED_LIST 0x00da1101 /* Location code information structure */
+#define FSP_RSP_GET_LED_LIST 0x00da9100
+#define FSP_CMD_RET_LED_BUFFER 0x00da1102 /* Location code buffer information */
+#define FSP_RSP_RET_LED_BUFFER 0x00da9100
+#define FSP_CMD_GET_LED_STATE 0x00da1103 /* Retrieve Indicator State */
+#define FSP_RSP_GET_LED_STATE 0x00da9100
+#define FSP_CMD_SET_LED_STATE 0x00da1104 /* Set Service Indicator State */
+#define FSP_RSP_SET_LED_STATE 0x00da9100
+
+/*
+ * Class 0xE0
+ *
+ * HACK ALERT: We mark E00A01 (associate serial port) as not needing
+ * a response. We need to do that because the FSP will send as a result
+ * an Open Virtual Serial of the same class *and* expect a reply before
+ * it will respond to associate serial port. That breaks our logic of
+ * supporting only one cmd/resp outstanding per class.
+ */
+#define FSP_CMD_HMC_INTF_QUERY 0x0e00100 /* FSP->HV */
+#define FSP_RSP_HMC_INTF_QUERY 0x0e08100 /* HV->FSP */
+#define FSP_CMD_ASSOC_SERIAL 0x0e00a01 /* HV->FSP: Associate with a port */
+#define FSP_RSP_ASSOC_SERIAL 0x0e08a00 /* FSP->HV */
+#define FSP_CMD_UNASSOC_SERIAL 0x0e00b01 /* HV->FSP: Deassociate */
+#define FSP_RSP_UNASSOC_SERIAL 0x0e08b00 /* FSP->HV */
+#define FSP_CMD_OPEN_VSERIAL 0x0e00601 /* FSP->HV: Open serial session */
+#define FSP_RSP_OPEN_VSERIAL 0x0e08600 /* HV->FSP */
+#define FSP_CMD_CLOSE_VSERIAL 0x0e00701 /* FSP->HV: Close serial session */
+#define FSP_RSP_CLOSE_VSERIAL 0x0e08700 /* HV->FSP */
+#define FSP_CMD_CLOSE_HMC_INTF 0x0e00300 /* FSP->HV: Close HMC interface */
+#define FSP_RSP_CLOSE_HMC_INTF 0x0e08300 /* HV->FSP */
+
+/*
+ * Class E1
+ */
+#define FSP_CMD_VSERIAL_IN 0x0e10100 /* FSP->HV */
+#define FSP_CMD_VSERIAL_OUT 0x0e10200 /* HV->FSP */
+
+/*
+ * Class E8
+ */
+#define FSP_CMD_READ_SRC 0x1e84a40 /* HV->FSP */
+#define FSP_CMD_DISP_SRC_INDIR 0x1e84a41 /* HV->FSP */
+#define FSP_CMD_DISP_SRC_DIRECT 0x1e84a42 /* HV->FSP */
+#define FSP_CMD_CLEAR_SRC 0x1e84b00 /* HV->FSP */
+#define FSP_CMD_DIS_SRC_ECHO 0x1e87600 /* HV->FSP */
+
+/*
+ * Class EB
+ */
+#define FSP_CMD_GET_VNVRAM_SIZE 0x01eb0100 /* HV->FSP */
+#define FSP_CMD_OPEN_VNVRAM 0x01eb0200 /* HV->FSP */
+#define FSP_CMD_READ_VNVRAM 0x01eb0300 /* HV->FSP */
+#define FSP_CMD_WRITE_VNVRAM 0x01eb0400 /* HV->FSP */
+#define FSP_CMD_GET_VNV_STATS 0x00eb0500 /* FSP->HV */
+#define FSP_RSP_GET_VNV_STATS 0x00eb8500
+#define FSP_CMD_FREE_VNV_STATS 0x00eb0600 /* FSP->HV */
+#define FSP_RSP_FREE_VNV_STATS 0x00eb8600
+
+/*
+ * Class 0xEE
+ */
+#define FSP_RSP_DIAG_LINK_ERROR 0x00ee1100 /* FSP->HV */
+#define FSP_RSP_DIAG_ACK_TIMEOUT 0x00ee0000 /* FSP->HV */
+
+/*
+ * Class F0
+ */
+#define FSP_CMD_LOAD_OCC 0x00f00100 /* FSP->HV */
+#define FSP_RSP_LOAD_OCC 0x00f08100 /* HV->FSP */
+#define FSP_CMD_LOAD_OCC_STAT 0x01f00300 /* HV->FSP */
+#define FSP_CMD_RESET_OCC 0x00f00200 /* FSP->HV */
+#define FSP_RSP_RESET_OCC 0x00f08200 /* HV->FSP */
+#define FSP_CMD_RESET_OCC_STAT 0x01f00400 /* HV->FSP */
+
+/*
+ * Class E4
+ */
+#define FSP_CMD_MEM_RES_CE 0x00e40300 /* FSP->HV: Memory resilience CE */
+#define FSP_CMD_MEM_RES_UE 0x00e40301 /* FSP->HV: Memory resilience UE */
+#define FSP_CMD_MEM_RES_UE_SCRB 0x00e40302 /* FSP->HV: UE detected by scrub */
+#define FSP_RSP_MEM_RES 0x00e48300 /* HV->FSP */
+#define FSP_CMD_MEM_DYN_DEALLOC 0x00e40500 /* FSP->HV: Dynamic mem dealloc */
+#define FSP_RSP_MEM_DYN_DEALLOC 0x00e48500 /* HV->FSP */
+
+/*
+ * Functions exposed to the rest of skiboot
+ */
+
+/* An FSP message */
+
+enum fsp_msg_state {
+ fsp_msg_unused = 0,
+ fsp_msg_queued,
+ fsp_msg_sent,
+ fsp_msg_wresp,
+ fsp_msg_done,
+ fsp_msg_timeout,
+ fsp_msg_incoming,
+ fsp_msg_response,
+ fsp_msg_cancelled,
+};
+
+struct fsp_msg {
+ /*
+ * User fields. Don't populate word0.seq (upper 16 bits), this
+ * will be done by fsp_queue_msg()
+ */
+ u8 dlen; /* not including word0/word1 */
+ u32 word0; /* seq << 16 | cmd */
+ u32 word1; /* mod << 8 | sub */
+ union {
+ u32 words[14];
+ u8 bytes[56];
+ } data;
+
+ /* Completion function. Called with no lock held */
+ void (*complete)(struct fsp_msg *msg);
+ void *user_data;
+
+ /*
+ * Driver updated fields
+ */
+
+ /* Current msg state */
+ enum fsp_msg_state state;
+
+ /* Set if the message expects a response */
+ bool response;
+
+ /* See if the message is a 'sync' message, and if so do we have to
+ * 'free' the message once sent. That is, do we need to wait on this
+ * message, till it gets sent to the FSP. This indication is useful
+ * only in the case where we experience a PSI link loss, or a FSP
+ * r/r, and need to queue up messages till the PSI link / FSP come back
+ * up again.
+ */
+ bool sync_msg;
+ bool auto_free;
+
+ /* Response will be filed by driver when response received */
+ struct fsp_msg *resp;
+
+ /* Internal queuing */
+ struct list_node link;
+};
+
+/* This checks if a message is still "in progress" in the FSP driver */
+static inline bool fsp_msg_busy(struct fsp_msg *msg)
+{
+ switch(msg->state) {
+ case fsp_msg_unused:
+ case fsp_msg_done:
+ case fsp_msg_timeout:
+ case fsp_msg_response: /* A response is considered a completed msg */
+ return false;
+ default:
+ break;
+ }
+ return true;
+}
+
+/* Initialize the FSP mailbox driver */
+extern void fsp_init(void);
+
+/* Perform the OPL sequence */
+extern void fsp_opl(void);
+
+/* Check if system has an FSP */
+extern bool fsp_present(void);
+
+/* Allocate and populate an fsp_msg structure
+ *
+ * WARNING: Do _NOT_ use free() on an fsp_msg, use fsp_freemsg()
+ * instead as we will eventually use pre-allocated message pools
+ */
+extern struct fsp_msg *fsp_allocmsg(bool alloc_response);
+extern struct fsp_msg *fsp_mkmsg(u32 cmd_sub_mod, u8 add_words, ...);
+
+/* Populate a pre-allocated msg */
+extern void fsp_fillmsg(struct fsp_msg *msg, u32 cmd_sub_mod, u8 add_words, ...);
+
+/* Free a message
+ *
+ * WARNING: This will also free an attached response if any
+ */
+extern void fsp_freemsg(struct fsp_msg *msg);
+
+/* Free a message and not the attached reply */
+extern void __fsp_freemsg(struct fsp_msg *msg);
+
+/* Cancel a message from the msg queue
+ *
+ * WARNING: * This is intended for use only in the FSP r/r scenario.
+ * * This will also free an attached response if any
+ */
+extern void fsp_cancelmsg(struct fsp_msg *msg);
+
+/* Enqueue it in the appropriate FSP queue
+ *
+ * NOTE: This supports being called with the FSP lock already
+ * held. This is the only function in this module that does so
+ * and is meant to be used that way for sending serial "poke"
+ * commands to the FSP.
+ */
+extern int fsp_queue_msg(struct fsp_msg *msg,
+ void (*comp)(struct fsp_msg *msg));
+
+/* Synchronously send a command. If there's a response, the status is
+ * returned as a positive number. A negative result means an error
+ * sending the message.
+ *
+ * If autofree is set, the message and the reply (if any) are freed
+ * after extracting the status. If not set, you are responsible for
+ * freeing both the message and an eventual response
+ *
+ * NOTE: This will call fsp_queue_msg(msg, NULL), hence clearing the
+ * completion field of the message. No synchronous message is expected
+ * to utilize asynchronous completions.
+ */
+extern int fsp_sync_msg(struct fsp_msg *msg, bool autofree);
+
+/* Process FSP mailbox activity */
+extern void fsp_poll(void);
+
+/* Handle FSP interrupts */
+extern void fsp_interrupt(void);
+
+/* An FSP client is interested in messages for a given class */
+struct fsp_client {
+ /* Return true to "own" the message (you can free it) */
+ bool (*message)(u32 cmd_sub_mod, struct fsp_msg *msg);
+ struct list_node link;
+};
+
+/* WARNING: Command class FSP_MCLASS_IPL is aliased to FSP_MCLASS_SERVICE,
+ * thus a client of one will get both types of messages.
+ *
+ * WARNING: Client register/unregister takes *NO* lock. These are expected
+ * to be called early at boot before CPUs are brought up and before
+ * fsp_poll() can race. The client callback is called with no lock held.
+ */
+extern void fsp_register_client(struct fsp_client *client, u8 msgclass);
+extern void fsp_unregister_client(struct fsp_client *client, u8 msgclass);
+
+/* FSP TCE map/unmap functions */
+extern void fsp_tce_map(u32 offset, void *addr, u32 size);
+extern void fsp_tce_unmap(u32 offset, u32 size);
+extern void *fsp_inbound_buf_from_tce(u32 tce_token);
+
+/* Data fetch helper */
+extern uint32_t fsp_adjust_lid_side(uint32_t lid_no);
+extern int fsp_fetch_data(uint8_t flags, uint16_t id, uint32_t sub_id,
+ uint32_t offset, void *buffer, size_t *length);
+extern int fsp_fetch_data_queue(uint8_t flags, uint16_t id, uint32_t sub_id,
+ uint32_t offset, void *buffer, size_t *length,
+ void (*comp)(struct fsp_msg *msg));
+
+/* FSP console stuff */
+extern void fsp_console_preinit(void);
+extern void fsp_console_init(void);
+extern void fsp_console_add_nodes(void);
+extern void fsp_console_select_stdout(void);
+extern void fsp_console_reset(void);
+extern void fsp_console_poll(void *);
+
+/* Mark FSP lock */
+extern void fsp_used_by_console(void);
+
+/* NVRAM */
+extern int fsp_nvram_info(uint32_t *total_size);
+extern int fsp_nvram_start_read(void *dst, uint32_t src, uint32_t len);
+extern int fsp_nvram_write(uint32_t offset, void *src, uint32_t size);
+extern void fsp_nvram_wait_open(void);
+
+/* RTC */
+extern void fsp_rtc_init(void);
+extern int fsp_rtc_get_cached_tod(uint32_t *year_month_day,
+ uint64_t *hour_minute_second_millisecond);
+
+/* ELOG */
+extern void fsp_elog_read_init(void);
+extern void fsp_elog_write_init(void);
+
+/* Code update */
+extern void fsp_code_update_init(void);
+extern void fsp_code_update_wait_vpd(bool is_boot);
+
+/* Dump */
+extern void fsp_dump_init(void);
+extern void fsp_fips_dump_notify(uint32_t dump_id, uint32_t dump_len);
+
+/* MDST table */
+extern void fsp_mdst_table_init(void);
+
+/* This can be set by the fsp_opal_update_flash so that it can
+ * get called just reboot we reboot shutdown the machine.
+ */
+extern int (*fsp_flash_term_hook)(void);
+
+/* Surveillance */
+extern void fsp_init_surveillance(void);
+extern void fsp_surv_query(void);
+
+/* Reset/Reload */
+extern void fsp_reinit_fsp(void);
+extern void fsp_trigger_reset(void);
+
+/* FSP memory errors */
+extern void fsp_memory_err_init(void);
+
+/* Sensor */
+extern void fsp_init_sensor(void);
+
+/* Diagnostic */
+extern void fsp_init_diag(void);
+
+/* LED */
+extern void fsp_led_init(void);
+extern void fsp_get_led_list(struct fsp_msg *msg);
+extern void fsp_free_led_list_buf(struct fsp_msg *msg);
+extern void fsp_get_led_state(struct fsp_msg *msg);
+extern void fsp_set_led_state(struct fsp_msg *msg);
+
+#endif /* __FSP_H */
diff --git a/include/gx.h b/include/gx.h
new file mode 100644
index 0000000..f633892
--- /dev/null
+++ b/include/gx.h
@@ -0,0 +1,59 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Definitions relative to the P7 and P7+ GX controller
+ */
+#ifndef __GX_H
+#define __GX_H
+
+#include <bitutils.h>
+
+/* P7 GX Mode 1 register (contains PSI BUID) */
+#define GX_P7_MODE1_REG 0x0201180A
+#define GX_P7_MODE1_PSI_BUID_MASK PPC_BITMASK(18,26)
+#define GX_P7_MODE1_PSI_BUID_LSH PPC_BITLSHIFT(26)
+#define GX_P7_MODE1_PSI_BUID_DISABLE PPC_BIT(27)
+
+/* P7+ GX Mode 4 register (PSI and NX BUIDs ) */
+#define GX_P7P_MODE4_REG 0x02011811
+#define GX_P7P_MODE4_ENABLE_NX_BUID PPC_BIT(0)
+#define GX_P7P_MODE4_NX_BUID_BASE_MASK PPC_BITMASK(1,9)
+#define GX_P7P_MODE4_NX_BUID_BASE_LSH PPC_BITLSHIFT(9)
+#define GX_P7P_MODE4_NX_BUID_MASK_MASK PPC_BITMASK(10,18)
+#define GX_P7P_MODE4_NX_BUID_MASK_LSH PPC_BITLSHIFT(18)
+#define GX_P7P_MODE4_PSI_BUID_MASK PPC_BITMASK(19,27)
+#define GX_P7P_MODE4_PSI_BUID_LSH PPC_BITLSHIFT(27)
+#define GX_P7P_MODE4_PSI_BUID_DISABLE PPC_BIT(28)
+
+/* P7 GX TCE BAR and mask */
+#define GX_P7_GX0_TCE_BAR 0x02011845
+#define GX_P7_TCE_BAR_ADDR_MASK PPC_BITMASK(0,25)
+#define GX_P7_TCE_BAR_ADDR_LSH PPC_BITLSHIFT(25)
+#define GX_P7_TCE_BAR_ADDR_SHIFT PPC_BITLSHIFT(43)
+#define GX_P7_TCE_BAR_ENABLE PPC_BIT(26)
+#define GX_P7_GX0_TCE_MASK 0x0201184B
+#define GX_P7_TCE_MASK_MASK PPC_BITMASK(0,25)
+#define GX_P7_TCE_MASK_LSH PPC_BITLSHIFT(25)
+#define GX_P7_GX1_TCE_BAR 0x02011885
+#define GX_P7_GX1_TCE_MASK 0x0201188B
+
+
+extern int gx_configure_psi_buid(uint32_t chip, uint32_t buid);
+extern int gx_configure_tce_bar(uint32_t chip, uint32_t gx, uint64_t addr,
+ uint64_t size);
+
+#endif /* __GX_H */
diff --git a/include/hostservices.h b/include/hostservices.h
new file mode 100644
index 0000000..23e2a83
--- /dev/null
+++ b/include/hostservices.h
@@ -0,0 +1,36 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HOSTSERVICES_H
+#define __HOSTSERVICES_H
+
+bool hservices_init(void);
+
+int host_services_occ_load(void);
+int host_services_occ_start(void);
+void host_services_occ_base_setup(void);
+
+/* No LID can be larger than 16M, but OCC lid is less than 1 MB */
+
+#define HBRT_LOAD_LID_SIZE 0x100000 /* 1MB */
+
+/* TODO: Detect OCC lid size at runtime */
+
+/* Homer and OCC area size */
+#define HOMER_IMAGE_SIZE 0x400000 /* 4MB per-chip */
+#define OCC_COMMON_SIZE 0x800000 /* 8MB */
+
+#endif /* __HOSTSERVICES_H */
diff --git a/include/interrupts.h b/include/interrupts.h
new file mode 100644
index 0000000..9239b86
--- /dev/null
+++ b/include/interrupts.h
@@ -0,0 +1,254 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __INTERRUPTS_H
+#define __INTERRUPTS_H
+
+#include <stdint.h>
+#include <ccan/list/list.h>
+
+/*
+ * Note about interrupt numbers on P7/P7+
+ * ======================================
+ *
+ * The form of an interrupt number in the system on P7/P7+ is as follow:
+ *
+ * | Node | T| Chip|GX| BUID | Level |
+ * |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|
+ *
+ * Where:
+ *
+ * - Node : The 3-bit node number
+ * - T : 1 for a Torrent chip, 0 otherwise
+ * - Chip : 2-bit chip number in a node
+ * - GX : GX bus identifier
+ * - BUID : Bus identifier (*)
+ * - Level : Interrupt number
+ *
+ * (*) The BUID/Level distinction is mostly historical, interrupt
+ * controllers such as the ICS in the PHBs "use" some of the
+ * low BUID bits as an extension to the interrupt number
+ *
+ * The NodeID and ChipID together form a 5-bit Processor Chip ID as
+ * found in the PIR or in the SPIRA data structures (without the T bit)
+ *
+ * PSI interrupt numbering scheme:
+ * -------------------------------
+ *
+ * This is tentatively deduced from stuff I found in some SCOM regs
+ * and in the BookIV. The PSIHB can be used to specify the 9-bit BUID,
+ * the Level is always 0. The doc also says that it prepends the 6-bit
+ * PowerBus chipID (Node + T + Chip). I *assume* that it also prepends
+ * a 0 in place of the GX bit.
+ *
+ * OPAL seems to be arbitrarily using a BUID value of 0x3, I shall do
+ * the same "just in case" :-)
+ *
+ * NOTE: From grep'ing around the giant SCOM file for "Build", I found
+ * what looks like a register in the GX controller (Mode1
+ * register) where the PSI BUID can be stored as well. From
+ * looking around with the FSP getscom command, it appears
+ * that both pHyp and OPAL set this consistently to the same
+ * value that appears in the PHB configuration.
+ *
+ * => This is confirmed. The NX needs a similar configuration, this
+ * tells the GX controller not to forward transactions for these
+ * BUIDs down the GX bus.
+ *
+ * PCI interrupt numbering scheme:
+ * -------------------------------
+ *
+ * See IOCs
+ *
+ * NX interrupt numbering scheme (p7+):
+ * ------------------------------------
+ *
+ * TBD
+ *
+ *
+ * Additional note about routing of interrupts in P7 and P7+
+ * =========================================================
+ *
+ * There are two on-chip sources of interrupts on these that need a
+ * special treatment: The PSI interrupt and the NX interrupts.
+ *
+ * The problem is that they use the same BUID space as the IO chips
+ * connected to the GX bus, so the GX controller needs to be told
+ * about these BUIDs in order to avoid forwarding them down the GX
+ * link (and possibly choking due to the lack of reply).
+ *
+ * The bad news is that it's all undocumented. The good news is that
+ * I found the info after chatting with Bill Daly (HW design) and
+ * looking at the SCOM register maps.
+ *
+ * The way to set that up differs between P7 and P7+:
+ *
+ * - On P7, it's in the GX_MODE1 register at SCOM 0x0201180A, which
+ * among other things, contains those bits:
+ *
+ * 18:26 PSI_BUID: BUID to be used to indicate the interrupt is
+ * for the PSI
+ * 27 DISABLE_PSI_BUID: set to 1 to disable the buid reservation
+ * for PSI
+ *
+ * So one must write the 9-bit BUID (without the top chipID) of the
+ * PSI interrupt in there and clear the disable bit.
+ *
+ * - On P7+ it's in the GX_MODE4 register at SCOM 0x02011811
+ *
+ * 0 ENABLE_NX_BUID: set to 1 to enable the buid reservation for nx
+ * 1:9 NX_BUID_BASE: BUID BASE to be used to indicate the interrupt
+ * is for the nx
+ * 10:18 NX_BUID_MASK: BUID mask for the nx buid base
+ * 19:27 PSI_BUID: BUID to be used to indicate the interrupt is for
+ * the PSI
+ * 28 DISABLE_PSI_BUID: set to 1 to disable the buid reservation
+ * for PSI
+ *
+ * Note: The NX_BUID_MASK should have bits set to 1 that are relevant for
+ * the comparison to NX_BUID_BASE, ie 4 interrupts means a mask
+ * value of b'111111100
+ */
+
+#define P7_PSI_IRQ_BUID 0x3 /* 9-bit BUID for the PSI interrupts */
+
+/* Extract individual components of an IRQ number */
+#define P7_IRQ_BUID(irq) (((irq) >> 4) & 0x1ff)
+#define P7_IRQ_GXID(irq) (((irq) >> 13) & 0x1)
+#define P7_IRQ_CHIP(irq) (((irq) >> 14) & 0x3)
+#define P7_IRQ_TBIT(irq) (((irq) >> 16) & 0x1)
+#define P7_IRQ_NODE(irq) (((irq) >> 17) & 0x7)
+
+/* Extract the "full BUID" (extension + BUID) */
+#define P7_IRQ_FBUID(irq) (((irq) >> 4) & 0xffff)
+
+/* BUID Extension (GX + CHIP + T + NODE) */
+#define P7_IRQ_BEXT(irq) (((irq) >> 13) & 0x7f)
+
+/* Strip extension from BUID */
+#define P7_BUID_BASE(buid) ((buid) & 0x1ff)
+
+
+/* Note about interrupt numbers on P8
+ * ==================================
+ *
+ * On P8 the interrupts numbers are just a flat space of 19-bit,
+ * there is no BUID or similar.
+ *
+ * However, various unit tend to require blocks of interrupt that
+ * are naturally power-of-two aligned
+ *
+ * Our P8 Interrupt map consits thus of dividing the chip space
+ * into 4 "blocks" of 2048 interrupts. Block 0 is for random chip
+ * interrupt sources (NX, PSI, OCC, ...) and keeps sources 0..15
+ * clear to avoid conflits with IPIs etc.... Block 1..3 are assigned
+ * to PHB 0..2 respectively.
+ *
+ * That gives us an interrupt number made of:
+ * 18 13 12 11 10 0
+ * | | | | | |
+ * +--------------------+------+-----------------------------+
+ * | Chip# | PHB# | IVE# |
+ * +--------------------+------+-----------------------------+
+ *
+ * We can thus support a max of 2^6 = 64 chips
+ *
+ * Each PHB supports 2K interrupt sources, which is shared by
+ * LSI and MSI. With default configuration, MSI would use range
+ * [0, 0x7f7] and LSI would use [0x7f8, 0x7ff]. The interrupt
+ * source should be combined with IRSN to form final hardware
+ * IRQ.
+ *
+ */
+
+#define P8_CHIP_IRQ_BASE(chip) ((chip) << 13)
+#define P8_CHIP_IRQ_BLOCK_BASE(chip, block) (P8_CHIP_IRQ_BASE(chip) \
+ | ((block) << 11))
+#define P8_IRQ_BLOCK_MISC 0
+#define P8_IRQ_BLOCK_PHB0 1
+#define P8_IRQ_BLOCK_PHB1 2
+#define P8_IRQ_BLOCK_PHB2 3
+
+#define P8_CHIP_IRQ_PHB_BASE(chip, phb) (P8_CHIP_IRQ_BLOCK_BASE(chip,\
+ (phb) + P8_IRQ_BLOCK_PHB0))
+
+#define P8_IRQ_TO_CHIP(irq) (((irq) >> 13) & 0x3f)
+#define P8_IRQ_TO_BLOCK(irq) (((irq) >> 11) & 0x03)
+#define P8_IRQ_TO_PHB(irq) (P8_IRQ_TO_BLOCK(irq) - \
+ P8_IRQ_BLOCK_PHB0)
+
+/* Assignment of the "MISC" block:
+ * -------------------------------
+ *
+ * PSI interface has 6 interrupt sources:
+ *
+ * FSP, OCC, FSI, LPC, Local error, Host error
+ *
+ * and thus needs a block of 8
+ */
+#define P8_IRQ_MISC_PSI_BASE 0x10 /* 0x10..0x17 */
+
+/* These are handled by skiboot */
+#define P8_IRQ_PSI_SKIBOOT_BASE 0
+#define P8_IRQ_PSI_FSP 0
+#define P8_IRQ_PSI_OCC 1
+#define P8_IRQ_PSI_FSI 2
+#define P8_IRQ_PSI_LPC 3
+#define P8_IRQ_PSI_LOCAL_ERR 4
+#define P8_IRQ_PSI_LOCAL_COUNT 5
+#define P8_IRQ_PSI_ALL_COUNT 6
+
+/* These are passed onto Linux */
+#define P8_IRQ_PSI_LINUX_BASE 5
+#define P8_IRQ_PSI_HOST_ERR 5 /* Used for UART */
+#define P8_IRQ_PSI_LINUX_COUNT 1
+
+/* TBD: NX, AS, ...
+ */
+
+/*
+ * IRQ sources register themselves here. If an "interrupts" callback
+ * is provided, then all interrupts in that source will appear in
+ * 'opal-interrupts' and will be handled by us.
+ */
+struct irq_source_ops {
+ int64_t (*set_xive)(void *data, uint32_t isn, uint16_t server,
+ uint8_t priority);
+ int64_t (*get_xive)(void *data, uint32_t isn, uint16_t *server,
+ uint8_t *priority);
+ void (*interrupt)(void *data, uint32_t isn);
+};
+
+extern void register_irq_source(const struct irq_source_ops *ops, void *data,
+ uint32_t start, uint32_t count);
+extern void unregister_irq_source(uint32_t start, uint32_t count);
+
+extern uint32_t get_psi_interrupt(uint32_t chip_id);
+
+extern struct dt_node *add_ics_node(void);
+extern void add_opal_interrupts(void);
+extern uint32_t get_ics_phandle(void);
+
+struct cpu_thread;
+
+extern void reset_cpu_icp(void);
+extern void icp_send_eoi(uint32_t interrupt);
+extern void icp_prep_for_rvwinkle(void);
+extern void icp_kick_cpu(struct cpu_thread *cpu);
+
+extern void init_interrupts(void);
+
+#endif /* __INTERRUPTS_H */
diff --git a/include/io.h b/include/io.h
new file mode 100644
index 0000000..45a385e
--- /dev/null
+++ b/include/io.h
@@ -0,0 +1,175 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __IO_H
+#define __IO_H
+
+#ifndef __ASSEMBLY__
+
+#include <compiler.h>
+#include <stdint.h>
+#include <processor.h>
+#include <ccan/endian/endian.h>
+
+/*
+ * IO access functions
+ *
+ * __in_beXX() / __out_beXX() : non-byteswap, no barrier
+ * in_beXX() / out_beXX() : non-byteswap, barrier
+ * in_leXX() / out_leXX() : byteswap, barrier
+ */
+
+static inline uint8_t __in_8(const volatile uint8_t *addr)
+{
+ uint8_t val;
+ asm volatile("lbzcix %0,0,%1" :
+ "=r"(val) : "r"(addr), "m"(*addr) : "memory");
+ return val;
+}
+
+static inline uint8_t in_8(const volatile uint8_t *addr)
+{
+ sync();
+ return __in_8(addr);
+}
+
+static inline uint16_t __in_be16(const volatile uint16_t *addr)
+{
+ uint16_t val;
+ asm volatile("lhzcix %0,0,%1" :
+ "=r"(val) : "r"(addr), "m"(*addr) : "memory");
+ return val;
+}
+
+static inline uint16_t in_be16(const volatile uint16_t *addr)
+{
+ sync();
+ return __in_be16(addr);
+}
+
+static inline uint16_t in_le16(const volatile uint16_t *addr)
+{
+ return bswap_16(in_be16(addr));
+}
+
+static inline uint32_t __in_be32(const volatile uint32_t *addr)
+{
+ uint32_t val;
+ asm volatile("lwzcix %0,0,%1" :
+ "=r"(val) : "r"(addr), "m"(*addr) : "memory");
+ return val;
+}
+
+static inline uint32_t in_be32(const volatile uint32_t *addr)
+{
+ sync();
+ return __in_be32(addr);
+}
+
+static inline uint32_t in_le32(const volatile uint32_t *addr)
+{
+ return bswap_32(in_be32(addr));
+}
+
+static inline uint64_t __in_be64(const volatile uint64_t *addr)
+{
+ uint64_t val;
+ asm volatile("ldcix %0,0,%1" :
+ "=r"(val) : "r"(addr), "m"(*addr) : "memory");
+ return val;
+}
+
+static inline uint64_t in_be64(const volatile uint64_t *addr)
+{
+ sync();
+ return __in_be64(addr);
+}
+
+static inline uint64_t in_le64(const volatile uint64_t *addr)
+{
+ return bswap_64(in_be64(addr));
+}
+
+static inline void __out_8(volatile uint8_t *addr, uint8_t val)
+{
+ asm volatile("stbcix %0,0,%1"
+ : : "r"(val), "r"(addr), "m"(*addr) : "memory");
+}
+
+static inline void out_8(volatile uint8_t *addr, uint8_t val)
+{
+ sync();
+ return __out_8(addr, val);
+}
+
+static inline void __out_be16(volatile uint16_t *addr, uint16_t val)
+{
+ asm volatile("sthcix %0,0,%1"
+ : : "r"(val), "r"(addr), "m"(*addr) : "memory");
+}
+
+static inline void out_be16(volatile uint16_t *addr, uint16_t val)
+{
+ sync();
+ return __out_be16(addr, val);
+}
+
+static inline void out_le16(volatile uint16_t *addr, uint16_t val)
+{
+ out_be16(addr, bswap_16(val));
+}
+
+static inline void __out_be32(volatile uint32_t *addr, uint32_t val)
+{
+ asm volatile("stwcix %0,0,%1"
+ : : "r"(val), "r"(addr), "m"(*addr) : "memory");
+}
+
+static inline void out_be32(volatile uint32_t *addr, uint32_t val)
+{
+ sync();
+ return __out_be32(addr, val);
+}
+
+static inline void out_le32(volatile uint32_t *addr, uint32_t val)
+{
+ out_be32(addr, bswap_32(val));
+}
+
+static inline void __out_be64(volatile uint64_t *addr, uint64_t val)
+{
+ asm volatile("stdcix %0,0,%1"
+ : : "r"(val), "r"(addr), "m"(*addr) : "memory");
+}
+
+static inline void out_be64(volatile uint64_t *addr, uint64_t val)
+{
+ sync();
+ return __out_be64(addr, val);
+}
+
+static inline void out_le64(volatile uint64_t *addr, uint64_t val)
+{
+ out_be64(addr, bswap_64(val));
+}
+
+/* Assistant to macros used to access PCI config space */
+#define in_le8 in_8
+#define out_le8 out_8
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __IO_H */
diff --git a/include/lock.h b/include/lock.h
new file mode 100644
index 0000000..f24e769
--- /dev/null
+++ b/include/lock.h
@@ -0,0 +1,83 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LOCK_H
+#define __LOCK_H
+
+#include <stdbool.h>
+
+struct lock {
+ /* Lock value has bit 63 as lock bit and the PIR of the owner
+ * in the top 32-bit
+ */
+ unsigned long lock_val;
+
+ /*
+ * Set to true if lock is involved in the console flush path
+ * in which case taking it will suspend console flushing
+ */
+ bool in_con_path;
+};
+
+/* Initializer */
+#define LOCK_UNLOCKED { .lock_val = 0, .in_con_path = 0 }
+
+/* Note vs. libc and locking:
+ *
+ * The printf() family of
+ * functions use stack based t buffers and call into skiboot
+ * underlying read() and write() which use a console lock.
+ *
+ * The underlying FSP console code will thus operate within that
+ * console lock.
+ *
+ * The libc does *NOT* lock stream buffer operations, so don't
+ * try to scanf() from the same FILE from two different processors.
+ *
+ * FSP operations are locked using an FSP lock, so all processors
+ * can safely call the FSP API
+ *
+ * Note about ordering:
+ *
+ * lock() is a full memory barrier. unlock() is a lwsync
+ *
+ */
+
+extern bool bust_locks;
+
+static inline void init_lock(struct lock *l)
+{
+ l->lock_val = 0;
+ l->in_con_path = false;
+}
+
+extern bool __try_lock(struct lock *l);
+extern bool try_lock(struct lock *l);
+extern void lock(struct lock *l);
+extern void unlock(struct lock *l);
+
+/* The debug output can happen while the FSP lock, so we need some kind
+ * of recursive lock support here. I don't want all locks to be recursive
+ * though, thus the caller need to explicitly call lock_recursive which
+ * returns false if the lock was already held by this cpu. If it returns
+ * true, then the caller shall release it when done.
+ */
+extern bool lock_recursive(struct lock *l);
+
+/* Called after per-cpu data structures are available */
+extern void init_locks(void);
+
+#endif /* __LOCK_H */
diff --git a/include/lpc.h b/include/lpc.h
new file mode 100644
index 0000000..47d1037
--- /dev/null
+++ b/include/lpc.h
@@ -0,0 +1,95 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LPC_H
+#define __LPC_H
+
+#include <opal.h>
+#include <ccan/endian/endian.h>
+
+/* Routines for accessing the LPC bus on Power8 */
+
+extern void lpc_init(void);
+
+/* Check for a default bus */
+extern bool lpc_present(void);
+
+/* Default bus accessors */
+extern int64_t lpc_write(enum OpalLPCAddressType addr_type, uint32_t addr,
+ uint32_t data, uint32_t sz);
+extern int64_t lpc_read(enum OpalLPCAddressType addr_type, uint32_t addr,
+ uint32_t *data, uint32_t sz);
+
+/* Mark LPC bus as used by console */
+extern void lpc_used_by_console(void);
+
+/*
+ * Simplified big endian FW accessors
+ */
+static inline int64_t lpc_fw_read32(uint32_t *val, uint32_t addr)
+{
+ return lpc_read(OPAL_LPC_FW, addr, val, 4);
+}
+
+static inline int64_t lpc_fw_write32(uint32_t val, uint32_t addr)
+{
+ return lpc_write(OPAL_LPC_FW, addr, cpu_to_be64(val), 4);
+}
+
+
+/*
+ * Simplified Little Endian IO space accessors
+ *
+ * Note: We do *NOT* handle unaligned accesses
+ */
+
+static inline void lpc_outb(uint8_t data, uint32_t addr)
+{
+ lpc_write(OPAL_LPC_IO, addr, data, 1);
+}
+
+static inline uint8_t lpc_inb(uint32_t addr)
+{
+ uint32_t d32;
+ int64_t rc = lpc_read(OPAL_LPC_IO, addr, &d32, 1);
+ return (rc == OPAL_SUCCESS) ? d32 : 0xff;
+}
+
+static inline void lpc_outw(uint16_t data, uint32_t addr)
+{
+ lpc_write(OPAL_LPC_IO, addr, cpu_to_le16(data), 2);
+}
+
+static inline uint16_t lpc_inw(uint32_t addr)
+{
+ uint32_t d32;
+ int64_t rc = lpc_read(OPAL_LPC_IO, addr, &d32, 2);
+ return (rc == OPAL_SUCCESS) ? le16_to_cpu(d32) : 0xffff;
+}
+
+static inline void lpc_outl(uint32_t data, uint32_t addr)
+{
+ lpc_write(OPAL_LPC_IO, addr, cpu_to_le32(data), 4);
+}
+
+static inline uint32_t lpc_inl(uint32_t addr)
+{
+ uint32_t d32;
+ int64_t rc = lpc_read(OPAL_LPC_IO, addr, &d32, 4);
+ return (rc == OPAL_SUCCESS) ? le32_to_cpu(d32) : 0xffffffff;
+}
+
+#endif /* __LPC_H */
diff --git a/include/mem-map.h b/include/mem-map.h
new file mode 100644
index 0000000..effd689
--- /dev/null
+++ b/include/mem-map.h
@@ -0,0 +1,114 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MEM_MAP_H
+#define __MEM_MAP_H
+
+/* This is our main offset for relocation. All our buffers
+ * are offset from that and our code relocates itself to
+ * that location
+ */
+#define SKIBOOT_BASE 0x30000000
+
+/* Stack size set to 16K, some of it will be used for
+ * machine check (see stack.h)
+ */
+#define STACK_SHIFT 14
+#define STACK_SIZE (1 << STACK_SHIFT)
+
+/* The NACA and other stuff in head.S need to be at the start: we
+ * give it 64k before placing the SPIRA and related data.
+ */
+#define SPIRA_OFF 0x00010000
+
+/* SPIRA is 2k, then follow with for proc_init_data (aka PROCIN).
+ * These need to be at fixed addresses in case we're ever little
+ * endian: linker can't endian reverse a pointer for us. Text, data
+ * et. al. follows this.
+ */
+#define PROCIN_OFF (SPIRA_OFF + 0x800)
+
+/* Initial MDST table like PROCIN, we need fixed addresses,
+ * we leave a 2k gap for PROCIN
+ */
+#define MDST_TABLE_OFF (SPIRA_OFF + 0x1000)
+
+/* We keep a gap of 2M for skiboot text & bss for now. We will
+ * then we have our heap which goes up to base + 14M (so 12M for
+ * now, though we can certainly reduce that a lot).
+ *
+ * Ideally, we should fix the heap end and use _end to basically
+ * initialize our heap so that it covers anything from _end to
+ * that heap end, avoiding wasted space.
+ *
+ * That's made a bit tricky however due to how we create those
+ * regions statically in mem_region.c, but still on the list of
+ * things to improve.
+ *
+ * As of this writing (2014/4/6), we use approc 512K for skiboot
+ * core and 2M of heap on a 1 socket machine.
+ */
+#define HEAP_BASE (SKIBOOT_BASE + 0x00200000)
+#define HEAP_SIZE 0x00c00000
+
+/* This is our PSI TCE table. It's 16K entries on P7 and 256K
+ * entries on P8
+ */
+#define PSI_TCE_TABLE_BASE (SKIBOOT_BASE + 0x00e00000)
+#define PSI_TCE_TABLE_SIZE_P7 0x00020000UL
+#define PSI_TCE_TABLE_SIZE_P8 0x00200000UL
+
+/* This is the location of our console buffer at base + 16M */
+#define INMEM_CON_START (SKIBOOT_BASE + 0x01000000)
+#define INMEM_CON_LEN 0x100000
+
+/* This is the location of HBRT console buffer at base + 17M */
+#define HBRT_CON_START (SKIBOOT_BASE + 0x01100000)
+#define HBRT_CON_LEN 0x100000
+
+/* Tell FSP to put the init data at base + 20M, allocate 8M */
+#define SPIRA_HEAP_BASE (SKIBOOT_BASE + 0x01200000)
+#define SPIRA_HEAP_SIZE 0x00800000
+
+/* Total size of the above area
+ *
+ * (Ensure this has at least a 64k alignment)
+ */
+#define SKIBOOT_SIZE 0x01a00000
+
+/* We start laying out the CPU stacks from here, indexed by PIR
+ * each stack is STACK_SIZE in size (naturally aligned power of
+ * two) and the bottom of the stack contains the cpu thread
+ * structure for the processor, so it can be obtained by a simple
+ * bit mask from the stack pointer.
+ *
+ * The size of this array is dynamically determined at boot time
+ */
+#define CPU_STACKS_BASE (SKIBOOT_BASE + SKIBOOT_SIZE)
+
+/*
+ * Address at which we load the kernel LID. This is also where
+ * we expect a passed-in kernel if booting without FSP and
+ * without a built-in kernel.
+ */
+#define KERNEL_LOAD_BASE ((void *)0x20000000)
+#define KERNEL_LOAD_SIZE 0x10000000
+
+/* Size allocated to build the device-tree */
+#define DEVICE_TREE_MAX_SIZE 0x80000
+
+
+#endif /* __MEM_MAP_H */
diff --git a/include/mem_region-malloc.h b/include/mem_region-malloc.h
new file mode 100644
index 0000000..9c772d2
--- /dev/null
+++ b/include/mem_region-malloc.h
@@ -0,0 +1,41 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MEM_REGION_MALLOC_H
+#define __MEM_REGION_MALLOC_H
+
+#define __loc2(line) #line
+#define __loc(line) __loc2(line)
+#define __location__ __FILE__ ":" __loc(__LINE__)
+
+void *__malloc(size_t size, const char *location);
+void *__zalloc(size_t size, const char *location);
+void *__realloc(void *ptr, size_t size, const char *location);
+void __free(void *ptr, const char *location);
+void *__memalign(size_t boundary, size_t size, const char *location);
+
+#define malloc(size) __malloc(size, __location__)
+#define zalloc(size) __zalloc(size, __location__)
+#define realloc(ptr, size) __realloc(ptr, size, __location__)
+#define free(ptr) __free(ptr, __location__)
+#define memalign(boundary, size) __memalign(boundary, size, __location__)
+
+void *__local_alloc(unsigned int chip, size_t size, size_t align,
+ const char *location);
+#define local_alloc(chip_id, size, align) \
+ __local_alloc((chip_id), (size), (align), __location__)
+
+#endif /* __MEM_REGION_MALLOC_H */
diff --git a/include/mem_region.h b/include/mem_region.h
new file mode 100644
index 0000000..b2547e5
--- /dev/null
+++ b/include/mem_region.h
@@ -0,0 +1,69 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MEMORY_REGION
+#define __MEMORY_REGION
+#include <ccan/list/list.h>
+#include <stdint.h>
+
+enum mem_region_type {
+ /* ranges allocatable by mem_alloc: this will be most of memory */
+ REGION_SKIBOOT_HEAP,
+
+ /* ranges used explicitly for skiboot, but not allocatable. eg .text */
+ REGION_SKIBOOT_FIRMWARE,
+
+ /* ranges reserved, possibly before skiboot init, eg HW framebuffer */
+ REGION_RESERVED,
+
+ /* ranges available for the OS, created by mem_region_release_unused */
+ REGION_OS,
+};
+
+/* An area of physical memory. */
+struct mem_region {
+ struct list_node list;
+ const char *name;
+ uint64_t start, len;
+ struct dt_node *mem_node;
+ enum mem_region_type type;
+ struct list_head free_list;
+};
+
+extern struct lock mem_region_lock;
+void *mem_alloc(struct mem_region *region, size_t size, size_t align,
+ const char *location);
+void mem_free(struct mem_region *region, void *mem,
+ const char *location);
+bool mem_resize(struct mem_region *region, void *mem, size_t len,
+ const char *location);
+size_t mem_size(const struct mem_region *region, const void *ptr);
+bool mem_check(const struct mem_region *region);
+void mem_region_release_unused(void);
+
+/* Specifically for working on the heap. */
+extern struct mem_region skiboot_heap;
+
+void mem_region_init(void);
+
+void mem_region_add_dt_reserved(void);
+
+/* Mark memory as reserved */
+void mem_reserve(const char *name, uint64_t start, uint64_t len);
+
+struct mem_region *find_mem_region(const char *name);
+
+#endif /* __MEMORY_REGION */
diff --git a/include/memory.h b/include/memory.h
new file mode 100644
index 0000000..ce0b22b
--- /dev/null
+++ b/include/memory.h
@@ -0,0 +1,23 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MEMORY_H
+#define __MEMORY_H
+
+/* This populate the @memory dt nodes. */
+extern void memory_parse(void);
+
+#endif /* __MEMORY_H */
diff --git a/include/nx.h b/include/nx.h
new file mode 100644
index 0000000..ef02ed5
--- /dev/null
+++ b/include/nx.h
@@ -0,0 +1,22 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NX_H
+#define __NX_H
+
+extern void nx_init(void);
+
+#endif /* __NX_H */
diff --git a/include/op-panel.h b/include/op-panel.h
new file mode 100644
index 0000000..dfb4e11
--- /dev/null
+++ b/include/op-panel.h
@@ -0,0 +1,67 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __OP_PANEL_H
+#define __OP_PANEL_H
+
+#include <stdint.h>
+
+/* Severity */
+enum op_severity {
+ OP_LOG = 0x4342, /* 'CB' - Progress info */
+ OP_WARN = 0x4542, /* 'EB' - Information condition */
+ OP_ERROR = 0x4442, /* 'DB' - Non fatal error */
+ OP_FATAL = 0x4242, /* 'BB' - Fatal error */
+};
+
+/* Module */
+enum op_module {
+ OP_MOD_CORE = 0x3030, /* '00' - Anything really */
+ OP_MOD_INIT = 0x3031, /* '01' - init */
+ OP_MOD_LOCK = 0x3032, /* '02' - spinlocks */
+ OP_MOD_FSP = 0x3033, /* '03' - FSP */
+ OP_MOD_FSPCON = 0x3034, /* '04' - FSPCON */
+ OP_MOD_CHIPTOD = 0x3035, /* '05' - ChipTOP */
+ OP_MOD_CPU = 0x3036, /* '06' - CPU bringup */
+ OP_MOD_MEM = 0x3037, /* '07' - Memory */
+ OP_MOD_XSCOM = 0x3038, /* '08' - XSCOM */
+};
+
+/* Common codes:
+ *
+ * 'BA010001' : Failed to load a kernel
+ * 'BA010002' : Failed to create a device-tree
+ * 'BA020000' : Locking already owned lock
+ * 'BA020001' : Unlocking unlocked lock
+ * 'BA020002' : Unlocking not-owned lock
+ * 'BA006666' : Abort
+ * 'BA050000' : Failed ChipTOD init/sync
+ * 'BA050001' : Failed to find a CPU on the master chip
+ * 'BA050002' : Master chip sync failed
+ * 'EA05xxx2' : Slave sync failed (xxx = PIR)
+ * 'BA070000' : Cannot find MS VPD or invalid
+ * 'BA070001' : MS VPD wrong size
+ * 'BA070002' : MS VPD doesn't have an MSAC
+ * 'BA070003' : MS VPD doesn't have a total config
+ */
+
+extern void op_display(enum op_severity, enum op_module, uint16_t code);
+
+extern void op_panel_disable_src_echo(void);
+extern void op_panel_clear_src(void);
+extern void fsp_oppanel_init(void);
+
+#endif /* __OP_PANEL_H */
diff --git a/include/opal-internal.h b/include/opal-internal.h
new file mode 100644
index 0000000..0330b28
--- /dev/null
+++ b/include/opal-internal.h
@@ -0,0 +1,234 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file opal-internal.h
+ * @brief OPAL related internal definitions
+ *
+ */
+
+#ifndef __OPAL_INTERNAL_H
+#define __OPAL_INTERNAL_H
+
+#include <skiboot.h>
+
+struct opal_table_entry {
+ void *func;
+ uint32_t token;
+ uint32_t nargs;
+};
+
+#define opal_call(__tok, __func, __nargs) \
+static struct opal_table_entry __e_##__func __used __section(".opal_table") = \
+{ .func = __func, .token = __tok, \
+ .nargs = __nargs + 0 * sizeof(__func( __test_args##__nargs )) }
+
+/* Make sure function takes args they claim. Look away now... */
+#define __test_args0
+#define __test_args1 0
+#define __test_args2 0,0
+#define __test_args3 0,0,0
+#define __test_args4 0,0,0,0
+#define __test_args5 0,0,0,0,0
+#define __test_args6 0,0,0,0,0,0
+#define __test_args7 0,0,0,0,0,0,0
+
+extern struct opal_table_entry __opal_table_start[];
+extern struct opal_table_entry __opal_table_end[];
+
+extern uint64_t opal_pending_events;
+
+extern struct dt_node *opal_node;
+
+extern void opal_table_init(void);
+extern void opal_update_pending_evt(uint64_t evt_mask, uint64_t evt_values);
+extern void add_opal_node(void);
+
+#define opal_register(token, func, nargs) \
+ __opal_reister((token) + 0*sizeof(func(__test_args##nargs)), \
+ (func), (nargs))
+extern void __opal_register(uint64_t token, void *func, unsigned num_args);
+
+/** @defgroup POLLER Poller
+ * Warning: no locking at the moment, do at init time only
+ * XXX TODO: Add the big RCU-ish "opal API lock" to protect us here
+ * which will also be used for other things such as runtime updates
+ * @ingroup OPAL_INTERNAL POLLER
+ * @{ */
+/** Function Doc */
+extern void opal_add_poller(void (*poller)(void *data), void *data);
+/** Function Doc */
+extern void opal_del_poller(void (*poller)(void *data));
+/** @} */
+
+/** @defgroup NOTIFIER Host Sync Notifier
+ * Warning: no locking, only call that from the init processor
+ * @ingroup OPAL_INTERNAL NOTIFIER
+ * @{ */
+/** Function Doc */
+extern void opal_add_host_sync_notifier(bool (*notify)(void *data), void *data);
+/** Function Doc */
+extern void opal_del_host_sync_notifier(bool (*notify)(void *data));
+/** @} */
+
+
+/** @ingroup OPAL_INTERNAL
+ * @defgroup ERR_TYPE Classification of error/events type reported on OPAL
+ * OPAL error/event type classification
+ * @ingroup OPAL_INTERNAL ERR_TYPE
+ * @{ */
+/** Platform Events/Errors: Report Machine Check Interrupt */
+#define OPAL_PLATFORM_ERR_EVT 0x01
+/** INPUT_OUTPUT: Report all I/O related events/errors */
+#define OPAL_INPUT_OUTPUT_ERR_EVT 0x02
+/** RESOURCE_DEALLOC: Hotplug events and errors */
+#define OPAL_RESOURCE_DEALLOC_ERR_EVT 0x03
+/** MISC: Miscellanous error */
+#define OPAL_MISC_ERR_EVT 0x04
+/** @} */
+
+/**
+ * @ingroup OPAL_INTERNAL
+ * @defgroup ERR_ID OPAL Subsystem IDs listed for reporting events/errors
+ * @ingroup ERR_ID OPAL_INTERNAL
+ * @{ */
+#define OPAL_PROCESSOR_SUBSYSTEM 0x10
+#define OPAL_MEMORY_SUBSYSTEM 0x20
+#define OPAL_IO_SUBSYSTEM 0x30
+#define OPAL_IO_DEVICES 0x40
+#define OPAL_CEC_HARDWARE 0x50
+#define OPAL_POWER_COOLING 0x60
+#define OPAL_MISC_SUBSYSTEM 0x70
+#define OPAL_SURVEILLANCE_ERR 0x7A
+#define OPAL_PLATFORM_FIRMWARE 0x80
+#define OPAL_SOFTWARE 0x90
+#define OPAL_EXTERNAL_ENV 0xA0
+/** @} */
+
+/**
+ * @ingroup OPAL_INTERNAL
+ * @defgroup ERR_SEV OPAL Error Severity
+ * During reporting an event/error the following represents how
+ * serious the logged event/error is. (Severity)
+ * @ingroup OPAL_INTERNAL ERR_SEV
+ * @{ */
+#define OPAL_INFO 0x00
+#define OPAL_RECOVERED_ERR_GENERAL 0x10
+/** @} */
+
+/**
+ * @ingroup ERR_SEV OPAL_INTERNAL
+ * @defgroup ERR_SEV_2 Predictive Error defines
+ * @ingroup ERR_SEV_2 ERR_SEV OPAL_INTERNAL
+ * @{ */
+/** 0x20 Generic predictive error */
+#define OPAL_PREDICTIVE_ERR_GENERAL 0x20
+/** 0x21 Predictive error, degraded performance */
+#define OPAL_PREDICTIVE_ERR_DEGRADED_PERF 0x21
+/** 0x22 Predictive error, fault may be corrected after reboot */
+#define OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT 0x22
+/**
+ * 0x23 Predictive error, fault may be corrected after reboot,
+ * degraded performance
+ */
+#define OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_BOOT_DEGRADE_PERF 0x23
+/** 0x24 Predictive error, loss of redundancy */
+#define OPAL_PREDICTIVE_ERR_LOSS_OF_REDUNDANCY 0x24
+/** @} */
+
+/** @ingroup ERR_SEV OPAL_INTERNAL
+ * @defgroup ERR_SEV_4 Unrecoverable Error defines
+ * @ingroup ERR_SEV_4 ERR_SEV OPAL_INTERNAL
+ * @{ */
+/** 0x40 Generic Unrecoverable error */
+#define OPAL_UNRECOVERABLE_ERR_GENERAL 0x40
+/** 0x41 Unrecoverable error bypassed with degraded performance */
+#define OPAL_UNRECOVERABLE_ERR_DEGRADE_PERF 0x41
+/** 0x44 Unrecoverable error bypassed with loss of redundancy */
+#define OPAL_UNRECOVERABLE_ERR_LOSS_REDUNDANCY 0x44
+/** 0x45 Unrecoverable error bypassed with loss of redundancy and performance */
+#define OPAL_UNRECOVERABLE_ERR_LOSS_REDUNDANCY_PERF 0x45
+/** 0x48 Unrecoverable error bypassed with loss of function */
+#define OPAL_UNRECOVERABLE_ERR_LOSS_OF_FUNCTION 0x48
+/** 0x50 In case of PANIC */
+#define OPAL_ERROR_PANIC 0x50
+/** @} */
+
+/**
+ * @ingroup OPAL_INTERNAL
+ * @defgroup OPAL_EVENT_SUB_TYPE Event Sub-Type
+ * This field provides additional information on the non-error
+ * event type
+ * @ingroup OPAL_EVENT_SUB_TYPE OPAL_INTERNAL
+ * @{ */
+#define OPAL_NA 0x00
+#define OPAL_MISCELLANEOUS_INFO_ONLY 0x01
+#define OPAL_PREV_REPORTED_ERR_RECTIFIED 0x10
+#define OPAL_SYS_RESOURCES_DECONFIG_BY_USER 0x20
+#define OPAL_SYS_RESOURCE_DECONFIG_PRIOR_ERR 0x21
+#define OPAL_RESOURCE_DEALLOC_EVENT_NOTIFY 0x22
+#define OPAL_CONCURRENT_MAINTENANCE_EVENT 0x40
+#define OPAL_CAPACITY_UPGRADE_EVENT 0x60
+#define OPAL_RESOURCE_SPARING_EVENT 0x70
+#define OPAL_DYNAMIC_RECONFIG_EVENT 0x80
+#define OPAL_NORMAL_SYS_PLATFORM_SHUTDOWN 0xD0
+#define OPAL_ABNORMAL_POWER_OFF 0xE0
+/** @} */
+
+/** @ingroup OPAL_INTERNAL
+ * Max user dump size is 14K */
+#define OPAL_LOG_MAX_DUMP 14336
+
+/**
+ * @struct opal_user_data_section
+ * @ingroup OPAL_INTERNAL
+ * Multiple user data sections
+ */
+struct opal_user_data_section {
+ uint32_t tag;
+ uint16_t size;
+ uint16_t component_id;
+ char data_dump[1];
+} __attribute__((__packed__));
+
+/**
+ * @struct opal_errorlog
+ * @ingroup OPAL_INTERNAL
+ * All the information regarding an error/event to be reported
+ * needs to populate this structure using pre-defined interfaces
+ * only
+ */
+struct opal_errorlog {
+
+ uint16_t component_id;
+ uint8_t error_event_type;
+ uint8_t subsystem_id;
+
+ uint8_t event_severity;
+ uint8_t event_subtype;
+ uint8_t user_section_count;
+ uint8_t elog_origin;
+
+ uint32_t user_section_size;
+ uint32_t reason_code;
+ uint32_t additional_info[4];
+
+ char user_data_dump[OPAL_LOG_MAX_DUMP];
+ struct list_node link;
+} __attribute__((__packed__));
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __OPAL_INTERNAL_H */
diff --git a/include/opal-msg.h b/include/opal-msg.h
new file mode 100644
index 0000000..2be7832
--- /dev/null
+++ b/include/opal-msg.h
@@ -0,0 +1,36 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __OPALMSG_H
+#define __OPALMSG_H
+
+#include <opal.h>
+
+#define OPAL_MAX_ASYNC_COMP 2
+
+int _opal_queue_msg(enum OpalMessageType msg_type, void *data,
+ void (*consumed)(void *data), size_t num_params,
+ const u64 *params);
+
+#define opal_queue_msg(msg_type, data, cb, ...) \
+ _opal_queue_msg(msg_type, data, cb, \
+ sizeof((u64[]) {__VA_ARGS__})/sizeof(u64), \
+ (u64[]) {__VA_ARGS__});
+
+void opal_init_msg(void);
+
+#endif /* __OPALMSG_H */
diff --git a/include/opal.h b/include/opal.h
new file mode 100644
index 0000000..0b80bb4
--- /dev/null
+++ b/include/opal.h
@@ -0,0 +1,912 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __OPAL_H
+#define __OPAL_H
+
+/****** OPAL APIs ******/
+
+/* Return codes */
+#define OPAL_SUCCESS 0
+#define OPAL_PARAMETER -1
+#define OPAL_BUSY -2
+#define OPAL_PARTIAL -3
+#define OPAL_CONSTRAINED -4
+#define OPAL_CLOSED -5
+#define OPAL_HARDWARE -6
+#define OPAL_UNSUPPORTED -7
+#define OPAL_PERMISSION -8
+#define OPAL_NO_MEM -9
+#define OPAL_RESOURCE -10
+#define OPAL_INTERNAL_ERROR -11
+#define OPAL_BUSY_EVENT -12
+#define OPAL_HARDWARE_FROZEN -13
+#define OPAL_WRONG_STATE -14
+#define OPAL_ASYNC_COMPLETION -15
+
+/* API Tokens (in r0) */
+#define OPAL_TEST 0
+#define OPAL_CONSOLE_WRITE 1
+#define OPAL_CONSOLE_READ 2
+#define OPAL_RTC_READ 3
+#define OPAL_RTC_WRITE 4
+#define OPAL_CEC_POWER_DOWN 5
+#define OPAL_CEC_REBOOT 6
+#define OPAL_READ_NVRAM 7
+#define OPAL_WRITE_NVRAM 8
+#define OPAL_HANDLE_INTERRUPT 9
+#define OPAL_POLL_EVENTS 10
+#define OPAL_PCI_SET_HUB_TCE_MEMORY 11
+#define OPAL_PCI_SET_PHB_TCE_MEMORY 12
+#define OPAL_PCI_CONFIG_READ_BYTE 13
+#define OPAL_PCI_CONFIG_READ_HALF_WORD 14
+#define OPAL_PCI_CONFIG_READ_WORD 15
+#define OPAL_PCI_CONFIG_WRITE_BYTE 16
+#define OPAL_PCI_CONFIG_WRITE_HALF_WORD 17
+#define OPAL_PCI_CONFIG_WRITE_WORD 18
+#define OPAL_SET_XIVE 19
+#define OPAL_GET_XIVE 20
+#define OPAL_GET_COMPLETION_TOKEN_STATUS 21 /* obsolete */
+#define OPAL_REGISTER_OPAL_EXCEPTION_HANDLER 22
+#define OPAL_PCI_EEH_FREEZE_STATUS 23
+#define OPAL_PCI_SHPC 24
+#define OPAL_CONSOLE_WRITE_BUFFER_SPACE 25
+#define OPAL_PCI_EEH_FREEZE_CLEAR 26
+#define OPAL_PCI_PHB_MMIO_ENABLE 27
+#define OPAL_PCI_SET_PHB_MEM_WINDOW 28
+#define OPAL_PCI_MAP_PE_MMIO_WINDOW 29
+#define OPAL_PCI_SET_PHB_TABLE_MEMORY 30
+#define OPAL_PCI_SET_PE 31
+#define OPAL_PCI_SET_PELTV 32
+#define OPAL_PCI_SET_MVE 33
+#define OPAL_PCI_SET_MVE_ENABLE 34
+#define OPAL_PCI_GET_XIVE_REISSUE 35
+#define OPAL_PCI_SET_XIVE_REISSUE 36
+#define OPAL_PCI_SET_XIVE_PE 37
+#define OPAL_GET_XIVE_SOURCE 38
+#define OPAL_GET_MSI_32 39
+#define OPAL_GET_MSI_64 40
+#define OPAL_START_CPU 41
+#define OPAL_QUERY_CPU_STATUS 42
+#define OPAL_WRITE_OPPANEL 43 /* unimplemented */
+#define OPAL_PCI_MAP_PE_DMA_WINDOW 44
+#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45
+#define OPAL_PCI_RESET 49
+#define OPAL_PCI_GET_HUB_DIAG_DATA 50
+#define OPAL_PCI_GET_PHB_DIAG_DATA 51
+#define OPAL_PCI_FENCE_PHB 52
+#define OPAL_PCI_REINIT 53
+#define OPAL_PCI_MASK_PE_ERROR 54
+#define OPAL_SET_SLOT_LED_STATUS 55
+#define OPAL_GET_EPOW_STATUS 56
+#define OPAL_SET_SYSTEM_ATTENTION_LED 57
+#define OPAL_RESERVED1 58
+#define OPAL_RESERVED2 59
+#define OPAL_PCI_NEXT_ERROR 60
+#define OPAL_PCI_EEH_FREEZE_STATUS2 61
+#define OPAL_PCI_POLL 62
+#define OPAL_PCI_MSI_EOI 63
+#define OPAL_PCI_GET_PHB_DIAG_DATA2 64
+#define OPAL_XSCOM_READ 65
+#define OPAL_XSCOM_WRITE 66
+#define OPAL_LPC_READ 67
+#define OPAL_LPC_WRITE 68
+#define OPAL_RETURN_CPU 69
+#define OPAL_REINIT_CPUS 70
+#define OPAL_ELOG_READ 71
+#define OPAL_ELOG_WRITE 72
+#define OPAL_ELOG_ACK 73
+#define OPAL_ELOG_RESEND 74
+#define OPAL_ELOG_SIZE 75
+#define OPAL_FLASH_VALIDATE 76
+#define OPAL_FLASH_MANAGE 77
+#define OPAL_FLASH_UPDATE 78
+#define OPAL_RESYNC_TIMEBASE 79
+#define OPAL_CHECK_TOKEN 80
+#define OPAL_DUMP_INIT 81
+#define OPAL_DUMP_INFO 82
+#define OPAL_DUMP_READ 83
+#define OPAL_DUMP_ACK 84
+#define OPAL_GET_MSG 85
+#define OPAL_CHECK_ASYNC_COMPLETION 86
+#define OPAL_SYNC_HOST_REBOOT 87
+#define OPAL_SENSOR_READ 88
+#define OPAL_GET_PARAM 89
+#define OPAL_SET_PARAM 90
+#define OPAL_DUMP_RESEND 91
+#define OPAL_ELOG_SEND 92
+#define OPAL_PCI_SET_PHB_CAPI_MODE 93
+#define OPAL_DUMP_INFO2 94
+#define OPAL_WRITE_OPPANEL_ASYNC 95
+#define OPAL_LAST 95
+
+#ifndef __ASSEMBLY__
+
+#include <compiler.h>
+#include <stdint.h>
+
+/* Other enums */
+
+enum OpalVendorApiTokens {
+ OPAL_START_VENDOR_API_RANGE = 1000, OPAL_END_VENDOR_API_RANGE = 1999
+};
+
+enum OpalFreezeState {
+ OPAL_EEH_STOPPED_NOT_FROZEN = 0,
+ OPAL_EEH_STOPPED_MMIO_FREEZE = 1,
+ OPAL_EEH_STOPPED_DMA_FREEZE = 2,
+ OPAL_EEH_STOPPED_MMIO_DMA_FREEZE = 3,
+ OPAL_EEH_STOPPED_RESET = 4,
+ OPAL_EEH_STOPPED_TEMP_UNAVAIL = 5,
+ OPAL_EEH_STOPPED_PERM_UNAVAIL = 6
+};
+enum OpalEehFreezeActionToken {
+ OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1,
+ OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2,
+ OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3
+};
+
+enum OpalPciStatusToken {
+ OPAL_EEH_NO_ERROR = 0,
+ OPAL_EEH_IOC_ERROR = 1,
+ OPAL_EEH_PHB_ERROR = 2,
+ OPAL_EEH_PE_ERROR = 3,
+ OPAL_EEH_PE_MMIO_ERROR = 4,
+ OPAL_EEH_PE_DMA_ERROR = 5
+};
+
+enum OpalPciErrorSeverity {
+ OPAL_EEH_SEV_NO_ERROR = 0,
+ OPAL_EEH_SEV_IOC_DEAD = 1,
+ OPAL_EEH_SEV_PHB_DEAD = 2,
+ OPAL_EEH_SEV_PHB_FENCED = 3,
+ OPAL_EEH_SEV_PE_ER = 4,
+ OPAL_EEH_SEV_INF = 5
+};
+
+enum OpalShpcAction {
+ OPAL_SHPC_GET_LINK_STATE = 0,
+ OPAL_SHPC_GET_SLOT_STATE = 1
+};
+
+enum OpalShpcLinkState {
+ OPAL_SHPC_LINK_DOWN = 0,
+ OPAL_SHPC_LINK_UP_x1 = 1,
+ OPAL_SHPC_LINK_UP_x2 = 2,
+ OPAL_SHPC_LINK_UP_x4 = 4,
+ OPAL_SHPC_LINK_UP_x8 = 8,
+ OPAL_SHPC_LINK_UP_x16 = 16,
+ OPAL_SHPC_LINK_UP_x32 = 32
+};
+enum OpalMmioWindowType {
+ OPAL_M32_WINDOW_TYPE = 1,
+ OPAL_M64_WINDOW_TYPE = 2,
+ OPAL_IO_WINDOW_TYPE = 3
+};
+enum OpalShpcSlotState {
+ OPAL_SHPC_DEV_NOT_PRESENT = 0,
+ OPAL_SHPC_DEV_PRESENT = 1
+};
+enum OpalShpcPowerState {
+ OPAL_SHPC_POWER_OFF = 0,
+ OPAL_SHPC_POWER_ON = 1
+};
+enum OpalExceptionHandler {
+ OPAL_MACHINE_CHECK_HANDLER = 1,
+ OPAL_HYPERVISOR_MAINTENANCE_HANDLER = 2,
+ OPAL_SOFTPATCH_HANDLER = 3
+};
+enum OpalPendingState {
+ OPAL_EVENT_OPAL_INTERNAL = 0x1,
+ OPAL_EVENT_NVRAM = 0x2,
+ OPAL_EVENT_RTC = 0x4,
+ OPAL_EVENT_CONSOLE_OUTPUT = 0x8,
+ OPAL_EVENT_CONSOLE_INPUT = 0x10,
+ OPAL_EVENT_ERROR_LOG_AVAIL = 0x20,
+ OPAL_EVENT_ERROR_LOG = 0x40,
+ OPAL_EVENT_EPOW = 0x80,
+ OPAL_EVENT_LED_STATUS = 0x100,
+ OPAL_EVENT_PCI_ERROR = 0x200,
+ OPAL_EVENT_DUMP_AVAIL = 0x400,
+ OPAL_EVENT_MSG_PENDING = 0x800,
+};
+
+/* Classification of error/events type reported on OPAL */
+/* Platform Events/Errors: Report Machine Check Interrupt */
+#define OPAL_PLATFORM_ERR_EVT 0x01
+/* INPUT_OUTPUT: Report all I/O related events/errors */
+#define OPAL_INPUT_OUTPUT_ERR_EVT 0x02
+/* RESOURCE_DEALLOC: Hotplug events and errors */
+#define OPAL_RESOURCE_DEALLOC_ERR_EVT 0x03
+/* MISC: Miscellanous error */
+#define OPAL_MISC_ERR_EVT 0x04
+
+/* OPAL Subsystem IDs listed for reporting events/errors */
+#define OPAL_PROCESSOR_SUBSYSTEM 0x10
+#define OPAL_MEMORY_SUBSYSTEM 0x20
+#define OPAL_IO_SUBSYSTEM 0x30
+#define OPAL_IO_DEVICES 0x40
+#define OPAL_CEC_HARDWARE 0x50
+#define OPAL_POWER_COOLING 0x60
+#define OPAL_MISC_SUBSYSTEM 0x70
+#define OPAL_SURVEILLANCE_ERR 0x7A
+#define OPAL_PLATFORM_FIRMWARE 0x80
+#define OPAL_SOFTWARE 0x90
+#define OPAL_EXTERNAL_ENV 0xA0
+
+/*
+ * During reporting an event/error the following represents
+ * how serious the logged event/error is. (Severity)
+ */
+#define OPAL_INFO 0x00
+#define OPAL_RECOVERED_ERR_GENERAL 0x10
+
+/* 0x2X series is to denote set of Predictive Error */
+/* 0x20 Generic predictive error */
+#define OPAL_PREDICTIVE_ERR_GENERAL 0x20
+/* 0x21 Predictive error, degraded performance */
+#define OPAL_PREDICTIVE_ERR_DEGRADED_PERF 0x21
+/* 0x22 Predictive error, fault may be corrected after reboot */
+#define OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT 0x22
+/*
+ * 0x23 Predictive error, fault may be corrected after reboot,
+ * degraded performance
+ */
+#define OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_BOOT_DEGRADE_PERF 0x23
+/* 0x24 Predictive error, loss of redundancy */
+#define OPAL_PREDICTIVE_ERR_LOSS_OF_REDUNDANCY 0x24
+
+/* 0x4X series for Unrecoverable Error */
+/* 0x40 Generic Unrecoverable error */
+#define OPAL_UNRECOVERABLE_ERR_GENERAL 0x40
+/* 0x41 Unrecoverable error bypassed with degraded performance */
+#define OPAL_UNRECOVERABLE_ERR_DEGRADE_PERF 0x41
+/* 0x44 Unrecoverable error bypassed with loss of redundancy */
+#define OPAL_UNRECOVERABLE_ERR_LOSS_REDUNDANCY 0x44
+/* 0x45 Unrecoverable error bypassed with loss of redundancy and performance */
+#define OPAL_UNRECOVERABLE_ERR_LOSS_REDUNDANCY_PERF 0x45
+/* 0x48 Unrecoverable error bypassed with loss of function */
+#define OPAL_UNRECOVERABLE_ERR_LOSS_OF_FUNCTION 0x48
+/* 0x50 In case of PANIC */
+#define OPAL_ERROR_PANIC 0x50
+
+/*
+ * OPAL Event Sub-type
+ * This field provides additional information on the non-error
+ * event type
+ */
+#define OPAL_NA 0x00
+#define OPAL_MISCELLANEOUS_INFO_ONLY 0x01
+#define OPAL_PREV_REPORTED_ERR_RECTIFIED 0x10
+#define OPAL_SYS_RESOURCES_DECONFIG_BY_USER 0x20
+#define OPAL_SYS_RESOURCE_DECONFIG_PRIOR_ERR 0x21
+#define OPAL_RESOURCE_DEALLOC_EVENT_NOTIFY 0x22
+#define OPAL_CONCURRENT_MAINTENANCE_EVENT 0x40
+#define OPAL_CAPACITY_UPGRADE_EVENT 0x60
+#define OPAL_RESOURCE_SPARING_EVENT 0x70
+#define OPAL_DYNAMIC_RECONFIG_EVENT 0x80
+#define OPAL_NORMAL_SYS_PLATFORM_SHUTDOWN 0xD0
+#define OPAL_ABNORMAL_POWER_OFF 0xE0
+
+/* Max user dump size is 14K */
+#define OPAL_LOG_MAX_DUMP 14336
+
+/* Multiple user data sections */
+struct __attribute__((__packed__))opal_user_data_section {
+ uint32_t tag;
+ uint16_t size;
+ uint16_t component_id;
+ char data_dump[1];
+};
+
+/* Machine check related definitions */
+enum OpalMCE_Version {
+ OpalMCE_V1 = 1,
+};
+
+enum OpalMCE_Severity {
+ OpalMCE_SEV_NO_ERROR = 0,
+ OpalMCE_SEV_WARNING = 1,
+ OpalMCE_SEV_ERROR_SYNC = 2,
+ OpalMCE_SEV_FATAL = 3,
+};
+
+enum OpalMCE_Disposition {
+ OpalMCE_DISPOSITION_RECOVERED = 0,
+ OpalMCE_DISPOSITION_NOT_RECOVERED = 1,
+};
+
+enum OpalMCE_Initiator {
+ OpalMCE_INITIATOR_UNKNOWN = 0,
+ OpalMCE_INITIATOR_CPU = 1,
+};
+
+enum OpalMCE_ErrorType {
+ OpalMCE_ERROR_TYPE_UNKNOWN = 0,
+ OpalMCE_ERROR_TYPE_UE = 1,
+ OpalMCE_ERROR_TYPE_SLB = 2,
+ OpalMCE_ERROR_TYPE_ERAT = 3,
+ OpalMCE_ERROR_TYPE_TLB = 4,
+};
+
+enum OpalMCE_UeErrorType {
+ OpalMCE_UE_ERROR_INDETERMINATE = 0,
+ OpalMCE_UE_ERROR_IFETCH = 1,
+ OpalMCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
+ OpalMCE_UE_ERROR_LOAD_STORE = 3,
+ OpalMCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
+};
+
+enum OpalMCE_SlbErrorType {
+ OpalMCE_SLB_ERROR_INDETERMINATE = 0,
+ OpalMCE_SLB_ERROR_PARITY = 1,
+ OpalMCE_SLB_ERROR_MULTIHIT = 2,
+};
+
+enum OpalMCE_EratErrorType {
+ OpalMCE_ERAT_ERROR_INDETERMINATE = 0,
+ OpalMCE_ERAT_ERROR_PARITY = 1,
+ OpalMCE_ERAT_ERROR_MULTIHIT = 2,
+};
+
+enum OpalMCE_TlbErrorType {
+ OpalMCE_TLB_ERROR_INDETERMINATE = 0,
+ OpalMCE_TLB_ERROR_PARITY = 1,
+ OpalMCE_TLB_ERROR_MULTIHIT = 2,
+};
+
+enum OpalThreadStatus {
+ OPAL_THREAD_INACTIVE = 0x0,
+ OPAL_THREAD_STARTED = 0x1,
+ OPAL_THREAD_UNAVAILABLE = 0x2
+};
+
+enum OpalPciBusCompare {
+ OpalPciBusAny = 0, /* Any bus number match */
+ OpalPciBus3Bits = 2, /* Match top 3 bits of bus number */
+ OpalPciBus4Bits = 3, /* Match top 4 bits of bus number */
+ OpalPciBus5Bits = 4, /* Match top 5 bits of bus number */
+ OpalPciBus6Bits = 5, /* Match top 6 bits of bus number */
+ OpalPciBus7Bits = 6, /* Match top 7 bits of bus number */
+ OpalPciBusAll = 7, /* Match bus number exactly */
+};
+
+enum OpalDeviceCompare {
+ OPAL_IGNORE_RID_DEVICE_NUMBER = 0,
+ OPAL_COMPARE_RID_DEVICE_NUMBER = 1
+};
+
+enum OpalFuncCompare {
+ OPAL_IGNORE_RID_FUNCTION_NUMBER = 0,
+ OPAL_COMPARE_RID_FUNCTION_NUMBER = 1
+};
+
+enum OpalPeAction {
+ OPAL_UNMAP_PE = 0,
+ OPAL_MAP_PE = 1
+};
+
+enum OpalPeltvAction {
+ OPAL_REMOVE_PE_FROM_DOMAIN = 0,
+ OPAL_ADD_PE_TO_DOMAIN = 1
+};
+
+enum OpalMveEnableAction {
+ OPAL_DISABLE_MVE = 0,
+ OPAL_ENABLE_MVE = 1
+};
+
+enum OpalM64Action {
+ OPAL_DISABLE_M64 = 0,
+ OPAL_ENABLE_M64_SPLIT = 1,
+ OPAL_ENABLE_M64_NON_SPLIT = 2
+};
+
+enum OpalPciResetScope {
+ OPAL_RESET_PHB_COMPLETE = 1,
+ OPAL_RESET_PCI_LINK = 2,
+ OPAL_RESET_PHB_ERROR = 3,
+ OPAL_RESET_PCI_HOT = 4,
+ OPAL_RESET_PCI_FUNDAMENTAL = 5,
+ OPAL_RESET_PCI_IODA_TABLE = 6
+};
+
+enum OpalPciReinitScope {
+ /*
+ * Note: we chose values that do not overlap
+ * OpalPciResetScope as OPAL v2 used the same
+ * enum for both
+ */
+ OPAL_REINIT_PCI_DEV = 1000
+};
+
+enum OpalPciResetState {
+ OPAL_DEASSERT_RESET = 0,
+ OPAL_ASSERT_RESET = 1
+};
+
+enum OpalPciMaskAction {
+ OPAL_UNMASK_ERROR_TYPE = 0,
+ OPAL_MASK_ERROR_TYPE = 1
+};
+
+enum OpalSlotLedType {
+ OPAL_SLOT_LED_ID_TYPE = 0,
+ OPAL_SLOT_LED_FAULT_TYPE = 1
+};
+
+enum OpalLedAction {
+ OPAL_TURN_OFF_LED = 0,
+ OPAL_TURN_ON_LED = 1,
+ OPAL_QUERY_LED_STATE_AFTER_BUSY = 2
+};
+
+enum OpalEpowStatus {
+ OPAL_EPOW_NONE = 0,
+ OPAL_EPOW_UPS = 1,
+ OPAL_EPOW_OVER_AMBIENT_TEMP = 2,
+ OPAL_EPOW_OVER_INTERNAL_TEMP = 3
+};
+
+enum OpalCheckTokenStatus {
+ OPAL_TOKEN_ABSENT = 0,
+ OPAL_TOKEN_PRESENT = 1
+};
+
+/*
+ * Address cycle types for LPC accesses. These also correspond
+ * to the content of the first cell of the "reg" property for
+ * device nodes on the LPC bus
+ */
+enum OpalLPCAddressType {
+ OPAL_LPC_MEM = 0,
+ OPAL_LPC_IO = 1,
+ OPAL_LPC_FW = 2,
+};
+
+enum OpalMessageType {
+ OPAL_MSG_ASYNC_COMP = 0, /* params[0] = token, params[1] = rc,
+ * additional params function-specific
+ */
+ OPAL_MSG_MEM_ERR,
+ OPAL_MSG_EPOW,
+ OPAL_MSG_SHUTDOWN,
+ OPAL_MSG_TYPE_MAX,
+};
+
+struct opal_msg {
+ uint32_t msg_type;
+ uint32_t reserved;
+ uint64_t params[8];
+};
+
+/* System parameter permission */
+enum OpalSysparamPerm {
+ OPAL_SYSPARAM_READ = 0x1,
+ OPAL_SYSPARAM_WRITE = 0x2,
+ OPAL_SYSPARAM_RW = (OPAL_SYSPARAM_READ | OPAL_SYSPARAM_WRITE),
+};
+
+struct opal_machine_check_event {
+ enum OpalMCE_Version version:8; /* 0x00 */
+ uint8_t in_use; /* 0x01 */
+ enum OpalMCE_Severity severity:8; /* 0x02 */
+ enum OpalMCE_Initiator initiator:8; /* 0x03 */
+ enum OpalMCE_ErrorType error_type:8; /* 0x04 */
+ enum OpalMCE_Disposition disposition:8; /* 0x05 */
+ uint8_t reserved_1[2]; /* 0x06 */
+ uint64_t gpr3; /* 0x08 */
+ uint64_t srr0; /* 0x10 */
+ uint64_t srr1; /* 0x18 */
+ union { /* 0x20 */
+ struct {
+ enum OpalMCE_UeErrorType ue_error_type:8;
+ uint8_t effective_address_provided;
+ uint8_t physical_address_provided;
+ uint8_t reserved_1[5];
+ uint64_t effective_address;
+ uint64_t physical_address;
+ uint8_t reserved_2[8];
+ } ue_error;
+
+ struct {
+ enum OpalMCE_SlbErrorType slb_error_type:8;
+ uint8_t effective_address_provided;
+ uint8_t reserved_1[6];
+ uint64_t effective_address;
+ uint8_t reserved_2[16];
+ } slb_error;
+
+ struct {
+ enum OpalMCE_EratErrorType erat_error_type:8;
+ uint8_t effective_address_provided;
+ uint8_t reserved_1[6];
+ uint64_t effective_address;
+ uint8_t reserved_2[16];
+ } erat_error;
+
+ struct {
+ enum OpalMCE_TlbErrorType tlb_error_type:8;
+ uint8_t effective_address_provided;
+ uint8_t reserved_1[6];
+ uint64_t effective_address;
+ uint8_t reserved_2[16];
+ } tlb_error;
+ } u;
+};
+
+/* FSP memory errors handling */
+enum OpalMemErr_Version {
+ OpalMemErr_V1 = 1,
+};
+
+enum OpalMemErrType {
+ OPAL_MEM_ERR_TYPE_RESILIENCE = 0,
+ OPAL_MEM_ERR_TYPE_DYN_DALLOC,
+};
+
+/* Memory Reilience error type */
+enum OpalMemErr_ResilErrType {
+ OPAL_MEM_RESILIENCE_CE = 0,
+ OPAL_MEM_RESILIENCE_UE,
+ OPAL_MEM_RESILIENCE_UE_SCRUB,
+};
+
+/* Dynamic Memory Deallocation type */
+enum OpalMemErr_DynErrType {
+ OPAL_MEM_DYNAMIC_DEALLOC = 0,
+};
+
+/* OpalMemoryErrorData->flags */
+#define OPAL_MEM_CORRECTED_ERROR 0x0001
+#define OPAL_MEM_THRESHOLD_EXCEEDED 0x0002
+#define OPAL_MEM_ACK_REQUIRED 0x8000
+
+struct OpalMemoryErrorData {
+ enum OpalMemErr_Version version:8; /* 0x00 */
+ enum OpalMemErrType type:8; /* 0x01 */
+ uint16_t flags; /* 0x02 */
+ uint8_t reserved_1[4]; /* 0x04 */
+
+ union {
+ /* Memory Resilience corrected/uncorrected error info */
+ struct {
+ enum OpalMemErr_ResilErrType resil_err_type:8;
+ uint8_t reserved_1[7];
+ uint64_t physical_address_start;
+ uint64_t physical_address_end;
+ } resilience;
+ /* Dynamic memory deallocation error info */
+ struct {
+ enum OpalMemErr_DynErrType dyn_err_type:8;
+ uint8_t reserved_1[7];
+ uint64_t physical_address_start;
+ uint64_t physical_address_end;
+ } dyn_dealloc;
+ } u;
+};
+
+enum {
+ OPAL_P7IOC_DIAG_TYPE_NONE = 0,
+ OPAL_P7IOC_DIAG_TYPE_RGC = 1,
+ OPAL_P7IOC_DIAG_TYPE_BI = 2,
+ OPAL_P7IOC_DIAG_TYPE_CI = 3,
+ OPAL_P7IOC_DIAG_TYPE_MISC = 4,
+ OPAL_P7IOC_DIAG_TYPE_I2C = 5,
+ OPAL_P7IOC_DIAG_TYPE_LAST = 6
+};
+
+struct OpalIoP7IOCErrorData {
+ uint16_t type;
+
+ /* GEM */
+ uint64_t gemXfir;
+ uint64_t gemRfir;
+ uint64_t gemRirqfir;
+ uint64_t gemMask;
+ uint64_t gemRwof;
+
+ /* LEM */
+ uint64_t lemFir;
+ uint64_t lemErrMask;
+ uint64_t lemAction0;
+ uint64_t lemAction1;
+ uint64_t lemWof;
+
+ union {
+ struct OpalIoP7IOCRgcErrorData {
+ uint64_t rgcStatus; /* 3E1C10 */
+ uint64_t rgcLdcp; /* 3E1C18 */
+ }rgc;
+ struct OpalIoP7IOCBiErrorData {
+ uint64_t biLdcp0; /* 3C0100, 3C0118 */
+ uint64_t biLdcp1; /* 3C0108, 3C0120 */
+ uint64_t biLdcp2; /* 3C0110, 3C0128 */
+ uint64_t biFenceStatus; /* 3C0130, 3C0130 */
+
+ uint8_t biDownbound; /* BI Downbound or Upbound */
+ }bi;
+ struct OpalIoP7IOCCiErrorData {
+ uint64_t ciPortStatus; /* 3Dn008 */
+ uint64_t ciPortLdcp; /* 3Dn010 */
+
+ uint8_t ciPort; /* Index of CI port: 0/1 */
+ }ci;
+ };
+};
+
+/**
+ * This structure defines the overlay which will be used to store PHB error
+ * data upon request.
+ */
+enum {
+ OPAL_PHB_ERROR_DATA_VERSION_1 = 1,
+};
+
+enum {
+ OPAL_PHB_ERROR_DATA_TYPE_P7IOC = 1,
+ OPAL_PHB_ERROR_DATA_TYPE_PHB3 = 2
+};
+
+enum {
+ OPAL_P7IOC_NUM_PEST_REGS = 128,
+ OPAL_PHB3_NUM_PEST_REGS = 256
+};
+
+struct OpalIoPhbErrorCommon {
+ uint32_t version;
+ uint32_t ioType;
+ uint32_t len;
+};
+
+struct OpalIoP7IOCPhbErrorData {
+ struct OpalIoPhbErrorCommon common;
+
+ uint32_t brdgCtl;
+
+ // P7IOC utl regs
+ uint32_t portStatusReg;
+ uint32_t rootCmplxStatus;
+ uint32_t busAgentStatus;
+
+ // P7IOC cfg regs
+ uint32_t deviceStatus;
+ uint32_t slotStatus;
+ uint32_t linkStatus;
+ uint32_t devCmdStatus;
+ uint32_t devSecStatus;
+
+ // cfg AER regs
+ uint32_t rootErrorStatus;
+ uint32_t uncorrErrorStatus;
+ uint32_t corrErrorStatus;
+ uint32_t tlpHdr1;
+ uint32_t tlpHdr2;
+ uint32_t tlpHdr3;
+ uint32_t tlpHdr4;
+ uint32_t sourceId;
+
+ uint32_t rsv3;
+
+ // Record data about the call to allocate a buffer.
+ uint64_t errorClass;
+ uint64_t correlator;
+
+ //P7IOC MMIO Error Regs
+ uint64_t p7iocPlssr; // n120
+ uint64_t p7iocCsr; // n110
+ uint64_t lemFir; // nC00
+ uint64_t lemErrorMask; // nC18
+ uint64_t lemWOF; // nC40
+ uint64_t phbErrorStatus; // nC80
+ uint64_t phbFirstErrorStatus; // nC88
+ uint64_t phbErrorLog0; // nCC0
+ uint64_t phbErrorLog1; // nCC8
+ uint64_t mmioErrorStatus; // nD00
+ uint64_t mmioFirstErrorStatus; // nD08
+ uint64_t mmioErrorLog0; // nD40
+ uint64_t mmioErrorLog1; // nD48
+ uint64_t dma0ErrorStatus; // nD80
+ uint64_t dma0FirstErrorStatus; // nD88
+ uint64_t dma0ErrorLog0; // nDC0
+ uint64_t dma0ErrorLog1; // nDC8
+ uint64_t dma1ErrorStatus; // nE00
+ uint64_t dma1FirstErrorStatus; // nE08
+ uint64_t dma1ErrorLog0; // nE40
+ uint64_t dma1ErrorLog1; // nE48
+ uint64_t pestA[OPAL_P7IOC_NUM_PEST_REGS];
+ uint64_t pestB[OPAL_P7IOC_NUM_PEST_REGS];
+};
+
+struct OpalIoPhb3ErrorData {
+ struct OpalIoPhbErrorCommon common;
+
+ uint32_t brdgCtl;
+
+ /* PHB3 UTL regs */
+ uint32_t portStatusReg;
+ uint32_t rootCmplxStatus;
+ uint32_t busAgentStatus;
+
+ /* PHB3 cfg regs */
+ uint32_t deviceStatus;
+ uint32_t slotStatus;
+ uint32_t linkStatus;
+ uint32_t devCmdStatus;
+ uint32_t devSecStatus;
+
+ /* cfg AER regs */
+ uint32_t rootErrorStatus;
+ uint32_t uncorrErrorStatus;
+ uint32_t corrErrorStatus;
+ uint32_t tlpHdr1;
+ uint32_t tlpHdr2;
+ uint32_t tlpHdr3;
+ uint32_t tlpHdr4;
+ uint32_t sourceId;
+
+ uint32_t rsv3;
+
+ /* Record data about the call to allocate a buffer */
+ uint64_t errorClass;
+ uint64_t correlator;
+
+ /* PHB3 MMIO Error Regs */
+ uint64_t nFir; /* 000 */
+ uint64_t nFirMask; /* 003 */
+ uint64_t nFirWOF; /* 008 */
+ uint64_t phbPlssr; /* 120 */
+ uint64_t phbCsr; /* 110 */
+ uint64_t lemFir; /* C00 */
+ uint64_t lemErrorMask; /* C18 */
+ uint64_t lemWOF; /* C40 */
+ uint64_t phbErrorStatus; /* C80 */
+ uint64_t phbFirstErrorStatus; /* C88 */
+ uint64_t phbErrorLog0; /* CC0 */
+ uint64_t phbErrorLog1; /* CC8 */
+ uint64_t mmioErrorStatus; /* D00 */
+ uint64_t mmioFirstErrorStatus; /* D08 */
+ uint64_t mmioErrorLog0; /* D40 */
+ uint64_t mmioErrorLog1; /* D48 */
+ uint64_t dma0ErrorStatus; /* D80 */
+ uint64_t dma0FirstErrorStatus; /* D88 */
+ uint64_t dma0ErrorLog0; /* DC0 */
+ uint64_t dma0ErrorLog1; /* DC8 */
+ uint64_t dma1ErrorStatus; /* E00 */
+ uint64_t dma1FirstErrorStatus; /* E08 */
+ uint64_t dma1ErrorLog0; /* E40 */
+ uint64_t dma1ErrorLog1; /* E48 */
+ uint64_t pestA[OPAL_PHB3_NUM_PEST_REGS];
+ uint64_t pestB[OPAL_PHB3_NUM_PEST_REGS];
+};
+
+enum {
+ OPAL_REINIT_CPUS_HILE_BE = (1 << 0),
+ OPAL_REINIT_CPUS_HILE_LE = (1 << 1),
+};
+
+typedef struct oppanel_line {
+ const char * line;
+ uint64_t line_len;
+} oppanel_line_t;
+
+/*
+ * SG entries used for code update
+ *
+ * WARNING: The current implementation requires each entry
+ * to represent a block that is 4k aligned *and* each block
+ * size except the last one in the list to be as well.
+ */
+struct opal_sg_entry {
+ void *data;
+ long length;
+};
+
+/*
+ * Candiate image SG list.
+ *
+ * length = VER | length
+ */
+struct opal_sg_list {
+ unsigned long length;
+ struct opal_sg_list *next;
+ struct opal_sg_entry entry[];
+};
+
+
+/****** Internal **********/
+#include <skiboot.h>
+
+
+/*
+ * All the information regarding an error/event to be reported
+ * needs to populate this structure using pre-defined interfaces
+ * only
+ */
+struct __attribute__((__packed__)) opal_errorlog {
+
+ uint16_t component_id;
+ uint8_t error_event_type;
+ uint8_t subsystem_id;
+
+ uint8_t event_severity;
+ uint8_t event_subtype;
+ uint8_t user_section_count;
+ uint8_t elog_origin;
+
+ uint32_t user_section_size;
+ uint32_t reason_code;
+ uint32_t additional_info[4];
+
+ char user_data_dump[OPAL_LOG_MAX_DUMP];
+ struct list_node link;
+};
+
+/* An opal table entry */
+struct opal_table_entry {
+ void *func;
+ uint32_t token;
+ uint32_t nargs;
+};
+
+#define opal_call(__tok, __func, __nargs) \
+static struct opal_table_entry __e_##__func __used __section(".opal_table") = \
+{ .func = __func, .token = __tok, \
+ .nargs = __nargs + 0 * sizeof(__func( __test_args##__nargs )) }
+
+/* Make sure function takes args they claim. Look away now... */
+#define __test_args0
+#define __test_args1 0
+#define __test_args2 0,0
+#define __test_args3 0,0,0
+#define __test_args4 0,0,0,0
+#define __test_args5 0,0,0,0,0
+#define __test_args6 0,0,0,0,0,0
+#define __test_args7 0,0,0,0,0,0,0
+
+extern struct opal_table_entry __opal_table_start[];
+extern struct opal_table_entry __opal_table_end[];
+
+extern uint64_t opal_pending_events;
+
+extern struct dt_node *opal_node;
+
+extern void opal_table_init(void);
+extern void opal_update_pending_evt(uint64_t evt_mask, uint64_t evt_values);
+extern void add_opal_node(void);
+
+#define opal_register(token, func, nargs) \
+ __opal_register((token) + 0*sizeof(func(__test_args##nargs)), \
+ (func), (nargs))
+extern void __opal_register(uint64_t token, void *func, unsigned num_args);
+
+/* Warning: no locking at the moment, do at init time only
+ *
+ * XXX TODO: Add the big RCU-ish "opal API lock" to protect us here
+ * which will also be used for other things such as runtime updates
+ */
+extern void opal_add_poller(void (*poller)(void *data), void *data);
+extern void opal_del_poller(void (*poller)(void *data));
+
+
+/*
+ * Warning: no locking, only call that from the init processor
+ */
+extern void opal_add_host_sync_notifier(bool (*notify)(void *data), void *data);
+extern void opal_del_host_sync_notifier(bool (*notify)(void *data));
+
+#endif /* __ASSEMBLY__ */
+#endif /* __OPAL_H */
diff --git a/include/p5ioc2-regs.h b/include/p5ioc2-regs.h
new file mode 100644
index 0000000..4cfd2e7
--- /dev/null
+++ b/include/p5ioc2-regs.h
@@ -0,0 +1,251 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __P5IOC2_REGS_H
+#define __P5IOC2_REGS_H
+
+/*
+ * IO HUB registers
+ *
+ * Most (all) of those registers support an AND access
+ * at address + 0x1000 and an OR access at address + 0x2000
+ */
+#define P5IOC2_REG_AND 0x1000
+#define P5IOC2_REG_OR 0x2000
+
+/* Internal BARs */
+#define P5IOC2_BAR0 0x0100
+#define P5IOC2_BAR1 0x0108
+#define P5IOC2_BAR2 0x0110
+#define P5IOC2_BAR3 0x0118
+#define P5IOC2_BAR4 0x0120
+#define P5IOC2_BAR5 0x0128
+#define P5IOC2_BAR6 0x0130
+#define P5IOC2_BAR7 0x0138
+#define P5IOC2_BARM0 0x0180
+#define P5IOC2_BARM1 0x0188
+#define P5IOC2_BARM2 0x0190
+#define P5IOC2_BARM3 0x0198
+#define P5IOC2_BARM4 0x01a0
+#define P5IOC2_BARM5 0x01a8
+#define P5IOC2_BARM6 0x01b0
+#define P5IOC2_BARM7 0x01b8
+#define P5IOC2_BAR(n) (0x100 + ((n) << 3))
+#define P5IOC2_BARM(n) (0x180 + ((n) << 3))
+
+/* Routing table */
+#define P5IOC2_TxRTE(x,n) (0x200 + ((x) << 7) + ((n) << 3))
+#define P5IOC2_TxRTE_VALID PPC_BIT(47)
+
+/* BUID routing table */
+#define P5IOC2_BUIDRTE(n) (0x600 + ((n) << 3))
+#define P5IOC2_BUIDRTE_VALID PPC_BIT(47)
+#define P5IOC2_BUIDRTE_RR_EOI PPC_BIT(48)
+#define P5IOC2_BUIDRTE_RR_RET PPC_BIT(49)
+
+/* Others */
+#define P5IOC2_FIRMC 0x0008 /* FIR Mask Checkstop */
+#define P5IOC2_CTL 0x0030 /* Control register part 1 */
+#define P5IOC2_CTL2 0x00c8 /* Control register part 2 */
+#define P5IOC2_DIRA 0x0090 /* Cache dir. address */
+#define P5IOC2_DIRD 0x0098 /* Cache dir. data */
+#define P5IOC2_IBASE 0x0048 /* Interrupt base address */
+#define P5IOC2_IRBM 0x00d8 /* Interrupt re-issue broadcast mask */
+#define P5IOC2_SID 0x0038 /* P5IOC2 ID register */
+#define P5IOC2_SID_BUID_BASE_MASK PPC_BITMASK(14,22)
+#define P5IOC2_SID_BUID_BASE_LSH PPC_BITLSHIFT(22)
+#define P5IOC2_SID_BUID_MASK_MASK PPC_BITMASK(27,30)
+#define P5IOC2_SID_BUID_MASK_LSH PPC_BITLSHIFT(30)
+#define P5IOC2_SBUID 0x00f8 /* P5IOC2 HUB BUID */
+
+/* XIPM area */
+#define P5IOC2_BUCO 0x40008
+#define P5IOC2_MIIP 0x40000
+#define P5IOC2_XINM 0x40010
+
+/* Xin/Xout area */
+#define P5IOC2_XIXO 0xf0030
+#define P5IOC2_XIXO_ENH_TCE PPC_BIT(0)
+
+/*
+ * Calgary registers
+ *
+ * CA0 is PCI-X and CA1 is PCIE, though the type can be discovered
+ * from registers so we'll simply let it do so
+ */
+
+#define CA_CCR 0x108
+#define CA_DEVBUID 0x118
+#define CA_DEVBUID_MASK PPC_BITMASK32(7,15)
+#define CA_DEVBUID_LSH PPC_BITLSHIFT32(15)
+#define CA_TAR0 0x580
+#define CA_TAR_HUBID_MASK PPC_BITMASK(0,5)
+#define CA_TAR_HUBID_LSH PPC_BITLSHIFT(5)
+#define CA_TAR_ALTHUBID_MASK PPC_BITMASK(6,11)
+#define CA_TAR_ALTHUBID_LSH PPC_BITLSHIFT(11)
+#define CA_TAR_TCE_ADDR_MASK PPC_BITMASK(16,48)
+#define CA_TAR_TCE_ADDR_LSH PPC_BITLSHIFT(48)
+#define CA_TAR_VALID PPC_BIT(60)
+#define CA_TAR_NUM_TCE_MASK PPC_BITMASK(61,63)
+#define CA_TAR_NUM_TCE_LSH PPC_BITLSHIFT(63)
+#define CA_TAR1 0x588
+#define CA_TAR2 0x590
+#define CA_TAR3 0x598
+#define CA_TARn(n) (0x580 + ((n) << 3))
+
+#define CA_PHBID0 0x650
+#define CA_PHBID_PHB_ENABLE PPC_BIT32(0)
+#define CA_PHBID_ADDRSPACE_ENABLE PPC_BIT32(1)
+#define CA_PHBID_PHB_TYPE_MASK PPC_BITMASK32(4,7)
+#define CA_PHBID_PHB_TYPE_LSH PPC_BITLSHIFT32(7)
+#define CA_PHBTYPE_PCIX1_0 0
+#define CA_PHBTYPE_PCIX2_0 1
+#define CA_PHBTYPE_PCIE_G1 4
+#define CA_PHBTYPE_PCIE_G2 5
+/* PCI-X bits */
+#define CA_PHBID_XMODE_EMBEDDED PPC_BIT32(8)
+#define CA_PHBID_XBUS_64BIT PPC_BIT32(9)
+#define CA_PHBID_XBUS_266MHZ PPC_BIT32(10)
+/* PCI-E bits */
+#define CA_PHBID_EWIDTH_MASK PPC_BITMASK32(8,10)
+#define CA_PHBID_EWIDTH_LSH PPC_BITLSHIFT32(10)
+#define CA_PHB_EWIDTH_X4 0
+#define CA_PHB_EWIDTH_X8 1
+#define CA_PHB_EWIDTH_X16 2
+#define CA_PHBID1 0x658
+#define CA_PHBID2 0x660
+#define CA_PHBID3 0x668
+#define CA_PHBIDn(n) (0x650 + ((n) << 3))
+
+/* PHB n reg base inside CA */
+#define CA_PHBn_REGS(n) (0x8000 + ((n) << 12))
+
+/*
+ * P5IOC2 PHB registers
+ */
+#define CAP_BUID 0x100
+#define CAP_BUID_MASK PPC_BITMASK32(7,15)
+#define CAP_BUID_LSH PPC_BITLSHIFT32(15)
+#define CAP_MSIBASE 0x108 /* Undocumented ! */
+#define CAP_DMACSR 0x110
+#define CAP_PLSSR 0x120
+#define CAP_PCADR 0x140
+#define CAP_PCADR_ENABLE PPC_BIT32(0)
+#define CAP_PCADR_FUNC_MASK PPC_BITMASK32(21,23)
+#define CAP_PCADR_FUNC_LSH PPC_BITLSHIFT32(23)
+#define CAP_PCADR_EXTOFF_MASK PPC_BITLSHIFT32(4,7)
+#define CAP_PCADR_EXTOFF_LSH PPC_BITLSHIFT32(7)
+#define CAP_PCDAT 0x130
+#define CAP_PCFGRW 0x160
+#define CAP_PCFGRW_ERR_RECOV_EN PPC_BIT32(1)
+#define CAP_PCFGRW_TCE_EN PPC_BIT32(2)
+#define CAP_PCFGRW_FREEZE_EN PPC_BIT32(3)
+#define CAP_PCFGRW_MMIO_FROZEN PPC_BIT32(4)
+#define CAP_PCFGRW_DMA_FROZEN PPC_BIT32(5)
+#define CAP_PCFGRW_ENHANCED_CFG_EN PPC_BIT32(6)
+#define CAP_PCFGRW_DAC_DISABLE PPC_BIT32(7)
+#define CAP_PCFGRW_2ND_MEM_SPACE_EN PPC_BIT32(9)
+#define CAP_PCFGRW_MASK_PLSSR_IRQ PPC_BIT32(10)
+#define CAP_PCFGRW_MASK_CSR_IRQ PPC_BIT32(11)
+#define CAP_PCFGRW_IO_SPACE_DIABLE PPC_BIT32(12)
+#define CAP_PCFGRW_SZ_MASK_IS_LIMIT PPC_BIT32(13)
+#define CAP_PCFGRW_MSI_EN PPC_BIT32(14)
+#define CAP_IOAD_L 0x170
+#define CAP_IOAD_H 0x180
+#define CAP_MEM1_L 0x190
+#define CAP_MEM1_H 0x1a0
+#define CAP_IOSZ 0x1b0
+#define CAP_MSZ1 0x1c0
+#define CAP_MEM_ST 0x1d0
+#define CAP_IO_ST 0x1e0
+#define CAP_AER 0x200
+#define CAP_BPR 0x210
+#define CAP_CRR 0x270
+#define CAP_CRR_RESET1 PPC_BIT32(0)
+#define CAP_CRR_RESET2 PPC_BIT32(1)
+#define CAP_XIVR0 0x400
+#define CAP_XIVR_PRIO_MASK 0x000000ff
+#define CAP_XIVR_PRIO_LSH 0
+#define CAP_XIVR_SERVER_MASK 0x0000ff00
+#define CAP_XIVR_SERVER_LSH 8
+#define CAP_XIVRn(n) (0x400 + ((n) << 4))
+#define CAP_MVE0 0x500
+#define CAP_MVE_VALID PPC_BIT32(0)
+#define CAP_MVE_TBL_OFF_MASK PPC_BITMASK32(13,15)
+#define CAP_MVE_TBL_OFF_LSH PPC_BITLSHIFT32(15)
+#define CAP_MVE_NUM_INT_MASK PPC_BITMASK32(18,19)
+#define CAP_MVE_NUM_INT_LSH PPC_BITLSHIFT32(19)
+#define CAP_MVE1 0x510
+#define CAP_MODE0 0x880
+#define CAP_MODE1 0x890
+#define CAP_MODE2 0x8a0
+#define CAP_MODE3 0x8b0
+
+/*
+ * SHPC Registers
+ */
+#define SHPC_LOGICAL_SLOT 0xb40
+#define SHPC_LOGICAL_SLOT_STATE_MASK 0x00000002
+#define SHPC_LOGICAL_SLOT_STATE_LSH 0
+#define SHPC_SLOT_STATE_POWER_ONLY 1
+#define SHPC_SLOT_STATE_ENABLED 2
+#define SHPC_SLOT_STATE_DISABLED 3
+#define SHPC_LOGICAL_SLOT_PRSNT_MASK 0x000000c00
+#define SHPC_LOGICAL_SLOT_PRSNT_LSH 10
+#define SHPC_SLOT_PRSTN_7_5W 0
+#define SHPC_SLOT_PRSTN_25W 1
+#define SHPC_SLOT_STATE_15W 2
+#define SHPC_SLOT_STATE_EMPTY 3
+
+/* UTL registers */
+#define UTL_SYS_BUS_CONTROL 0xc00
+#define UTL_STATUS 0xc04
+#define UTL_SYS_BUS_AGENT_STATUS 0xc08
+#define UTL_SYS_BUS_AGENT_ERR_EN 0xc0c
+#define UTL_SYS_BUS_AGENT_IRQ_EN 0xc10
+#define UTL_SYS_BUS_BURST_SZ_CONF 0xc20
+#define UTL_REVISION_ID 0xc24
+#define UTL_TX_NON_POST_DEBUG_STAT1 0xc30
+#define UTL_TX_NON_POST_DEBUG_STAT2 0xc34
+#define UTL_GBIF_READ_REQ_DEBUG 0xc38
+#define UTL_GBIF_WRITE_REQ_DEBUG 0xc3c
+#define UTL_GBIF_TX_COMP_DEBUG 0xc40
+#define UTL_GBIF_RX_COMP_DEBUG 0xc44
+#define UTL_OUT_POST_HDR_BUF_ALLOC 0xc60
+#define UTL_OUT_POST_DAT_BUF_ALLOC 0xc68
+#define UTL_IN_POST_HDR_BUF_ALLOC 0xc70
+#define UTL_IN_POST_DAT_BUF_ALLOC 0xc78
+#define UTL_OUT_NP_BUF_ALLOC 0xc80
+#define UTL_IN_NP_BUF_ALLOC 0xc88
+#define UTL_PCIE_TAGS_ALLOC 0xc90
+#define UTL_GBIF_READ_TAGS_ALLOC 0xc98
+#define UTL_PCIE_PORT_CONTROL 0xca0
+#define UTL_PCIE_PORT_STATUS 0xca4
+#define UTL_PCIE_PORT_ERR_EN 0xca8
+#define UTL_PCIE_PORT_IRQ_EN 0xcac
+#define UTL_RC_STATUS 0xcb0
+#define UTL_RC_ERR_EN 0xcb4
+#define UTL_RC_IRQ_EN 0xcb8
+#define UTL_PCI_PM_CONTROL 0xcc8
+#define UTL_PCIE_PORT_ID 0xccc
+#define UTL_TLP_DEBUG 0xcd0
+#define UTL_VC_CTL_DEBUG 0xcd4
+#define UTL_NP_BUFFER_DEBUG 0xcd8
+#define UTL_POSTED_BUFFER_DEBUG 0xcdc
+#define UTL_TX_FIFO_DEBUG 0xce0
+#define UTL_TLP_COMPL_DEBUG 0xce4
+
+#endif /* __P5IOC2_REGS_H */
diff --git a/include/p5ioc2.h b/include/p5ioc2.h
new file mode 100644
index 0000000..fb9ed1b
--- /dev/null
+++ b/include/p5ioc2.h
@@ -0,0 +1,184 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __P5IOC2_H
+#define __P5IOC2_H
+
+#include <stdint.h>
+#include <cec.h>
+#include <io.h>
+#include <cec.h>
+#include <pci.h>
+#include <lock.h>
+#include <device.h>
+
+#include <ccan/container_of/container_of.h>
+
+/*
+ * Various definitions which are the result of various
+ * things we have hard wired (routing etc...)
+ */
+
+/* It looks like our registers are at an offset from GX BAR 0 ... */
+#define P5IOC2_REGS_OFFSET 0x01F00000
+
+#define P5IOC2_CA0_REG_OFFSET 0 /* From BAR6, R0 */
+#define P5IOC2_CA1_REG_OFFSET 0x01000000 /* From BAR6, R1 */
+#define P5IOC2_CA0_MM_OFFSET 0 /* From BAR0, R0 and 1 */
+#define P5IOC2_CA1_MM_OFFSET 0x400000000ul /* From BAR0, R1 and 2 */
+#define P5IOC2_CA_PHB_COUNT 4
+#define P5IOC2_CA0_RIO_ID 2
+#define P5IOC2_CA1_RIO_ID 3
+#define P5IOC2_CA0_BUID 0x10
+#define P5IOC2_CA1_BUID 0x20
+
+/*
+ * Our memory space is slightly different than pHyp
+ * (or even BML). We do as follow:
+ *
+ * - IO space is in the Calgary MMIO, at (phb_index +1) * 1M
+ * (pHyp seems to mangle the IO space location) and is always
+ * 1M in size mapping to PCI 0
+ *
+ * - Memory space is in the BAR0 mapped region. Each PHB gets
+ * allocated a 4G window at base + (phb_index * 4G). It uses
+ * a portion of that space based on the chosen size of the
+ * MMIO space, typically 2G.
+ */
+#define MM_WINDOW_SIZE 0x100000000ul
+#define MM_PCI_START 0x80000000
+#define MM_PCI_SIZE 0x80000000
+#define IO_PCI_START 0x00000000
+#define IO_PCI_SIZE 0x00100000
+
+/*
+ * CAn interrupts
+ *
+ * Within Calgary BUID space
+ */
+#define P5IOC2_CA_HOST_IRQ 0
+#define P5IOC2_CA_SPCN_IRQ 1
+#define P5IOC2_CA_PERF_IRQ 2
+
+/*
+ * The PHB states are similar to P7IOC, see the explanation
+ * in p7ioc.h
+ */
+enum p5ioc2_phb_state {
+ /* First init state */
+ P5IOC2_PHB_STATE_UNINITIALIZED,
+
+ /* During PHB HW inits */
+ P5IOC2_PHB_STATE_INITIALIZING,
+
+ /* Set if the PHB is for some reason unusable */
+ P5IOC2_PHB_STATE_BROKEN,
+
+ /* Normal PHB functional state */
+ P5IOC2_PHB_STATE_FUNCTIONAL,
+};
+
+/*
+ * Structure for a PHB
+ */
+
+struct p5ioc2;
+
+struct p5ioc2_phb {
+ bool active; /* Is this PHB functional ? */
+ bool is_pcie;
+ uint8_t ca; /* CA0 or CA1 */
+ uint8_t index; /* 0..3 index inside CA */
+ void *ca_regs; /* Calgary regs */
+ void *regs; /* PHB regs */
+ struct lock lock;
+ uint32_t buid;
+ uint64_t mm_base;
+ uint64_t io_base;
+ int64_t ecap; /* cached PCI-E cap offset */
+ int64_t aercap; /* cached AER ecap offset */
+ enum p5ioc2_phb_state state;
+ uint64_t delay_tgt_tb;
+ uint64_t retries;
+ uint64_t xive_cache[16];
+ struct p5ioc2 *ioc;
+ struct phb phb;
+};
+
+static inline struct p5ioc2_phb *phb_to_p5ioc2_phb(struct phb *phb)
+{
+ return container_of(phb, struct p5ioc2_phb, phb);
+}
+
+extern void p5ioc2_phb_setup(struct p5ioc2 *ioc, struct p5ioc2_phb *p,
+ uint8_t ca, uint8_t index, bool active,
+ uint32_t buid);
+
+/*
+ * State structure for P5IOC2 IO HUB
+ */
+struct p5ioc2 {
+ /* Device node */
+ struct dt_node *dt_node;
+
+ /* MMIO regs for the chip */
+ void *regs;
+
+ /* BAR6 (matches GX BAR 1) is used for internal Calgary MMIO and
+ * for PCI IO space.
+ */
+ uint64_t bar6;
+
+ /* BAR0 (matches GX BAR 2) is used for PCI memory space */
+ uint64_t bar0;
+
+ /* Calgary 0 and 1 registers. We assume their BBAR values as such
+ * that CA0 is at bar6 and CA1 at bar6 + 16M
+ */
+ void* ca0_regs;
+ void* ca1_regs;
+
+ /* The large MM regions assigned off bar0 to CA0 and CA1 for use
+ * by their PHBs (16G each)
+ */
+ uint64_t ca0_mm_region;
+ uint64_t ca1_mm_region;
+
+ /* BUID base for the PHB. This does include the top bits
+ * (chip, GX bus ID, etc...). This is initialized from the
+ * SPIRA.
+ */
+ uint32_t buid_base;
+
+ /* TCE region set by the user */
+ uint64_t tce_base;
+ uint64_t tce_size;
+
+ /* Calgary 0 and 1 PHBs */
+ struct p5ioc2_phb ca0_phbs[P5IOC2_CA_PHB_COUNT];
+ struct p5ioc2_phb ca1_phbs[P5IOC2_CA_PHB_COUNT];
+
+ uint32_t host_chip;
+ uint32_t gx_bus;
+ struct io_hub hub;
+};
+
+static inline struct p5ioc2 *iohub_to_p5ioc2(struct io_hub *hub)
+{
+ return container_of(hub, struct p5ioc2, hub);
+}
+
+#endif /* __P5IOC2_H */
diff --git a/include/p7ioc-regs.h b/include/p7ioc-regs.h
new file mode 100644
index 0000000..daac1eb
--- /dev/null
+++ b/include/p7ioc-regs.h
@@ -0,0 +1,472 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __P7IOC_REGS_H
+#define __P7IOC_REGS_H
+
+/*
+ * Register definitions
+ *
+ * We only define some registers here. Ideally we should auto-generate
+ * the full list from the spec. For now I add them as I need them
+ */
+
+/* RGC GEM registers */
+#define P7IOC_GEM_XFIR 0x3E0008
+#define P7IOC_GEM_RFIR 0x3E0010
+#define P7IOC_GEM_RIRQFIR 0x3E0018
+#define P7IOC_GEM_MASK 0x3E0020
+#define P7IOC_GEM_RWOF 0x3E0028
+
+/* LEM register base */
+#define P7IOC_RGC_LEM_BASE 0x3E1E00
+#define P7IOC_BI_UP_LEM_BASE 0x3C0000
+#define P7IOC_BI_DOWN_LEM_BASE 0x3C0050
+#define P7IOC_CI_PORTn_LEM_BASE(n) (0x3d0200 | ((n) * 0x1000))
+#define P7IOC_PHBn_LEM_BASE(n) (0x000C00 | ((n) * 0x10000))
+#define P7IOC_MISC_LEM_BASE 0x3EA000
+#define P7IOC_I2C_LEM_BASE 0x3EB000
+
+/* LEM register offset */
+#define P7IOC_LEM_FIR_OFFSET 0x00
+#define P7IOC_LEM_FIR_AND_OFFSET 0x08
+#define P7IOC_LEM_FIR_OR_OFFSET 0x10
+#define P7IOC_LEM_ERR_MASK_OFFSET 0x18
+#define P7IOC_LEM_ERR_MASK_AND_OFFSET 0x20
+#define P7IOC_LEM_ERR_MASK_OR_OFFSET 0x28
+#define P7IOC_LEM_ACTION_0_OFFSET 0x30
+#define P7IOC_LEM_ACTION_1_OFFSET 0x38
+#define P7IOC_LEM_WOF_OFFSET 0x40
+
+/* HSS registers */
+#define P7IOC_HSS_BASE 0x3E8000
+#define P7IOC_HSS_STRIDE 0x200
+#define P7IOC_HSSn_CTL2_OFFSET 0x10
+#define P7IOC_HSSn_CTL3_OFFSET 0x18
+#define P7IOC_HSSn_CTL8_OFFSET 0x40
+#define P7IOC_HSSn_CTL9_OFFSET 0x48
+#define P7IOC_HSSn_CTL10_OFFSET 0x50
+#define P7IOC_HSSn_CTL11_OFFSET 0x58
+#define P7IOC_HSSn_CTL12_OFFSET 0x60
+#define P7IOC_HSSn_CTL13_OFFSET 0x68
+#define P7IOC_HSSn_CTL14_OFFSET 0x70
+#define P7IOC_HSSn_CTL15_OFFSET 0x78
+#define P7IOC_HSSn_CTL16_OFFSET 0x80
+#define P7IOC_HSSn_CTL17_OFFSET 0x88
+#define P7IOC_HSSn_CTL18_OFFSET 0x90
+#define P7IOC_HSSn_CTL19_OFFSET 0x98
+#define P7IOC_HSSn_CTL20_OFFSET 0xa0
+#define P7IOC_HSSn_CTL21_OFFSET 0xa8
+#define P7IOC_HSSn_CTL22_OFFSET 0xb0
+#define P7IOC_HSSn_CTL23_OFFSET 0xb8
+
+/* CI Routing registers & helper macros */
+#define P7IOC_CI_RMATC_REG(i) (0x3D0400ul + ((i) << 4))
+#define P7IOC_CI_RMASK_REG(i) (0x3D0408ul + ((i) << 4))
+
+#define P7IOC_CI_RMATC_PORT(n) PPC_BIT(n)
+#define P7IOC_CI_RMATC_ADDR_VALID PPC_BIT(16)
+#define P7IOC_CI_RMATC_BUID_VALID PPC_BIT(17)
+#define P7IOC_CI_RMATC_TYPE_VALID PPC_BIT(18)
+
+/* AIB Addresses are 48-bit, the top 32 are used in
+ * the routing tables, we thus shift by 16
+ */
+#define P7IOC_CI_RMATC_ENCODE_ADDR(addr) ((uint32_t)((addr) >> 16))
+#define P7IOC_CI_RMATC_ENCODE_BUID(buid) ((uint32_t)((buid) << 20))
+#define P7IOC_CI_RMATC_ENCODE_TYPE(type) ((uint32_t)(type))
+
+/* CI port numbers */
+#define P7IOC_CI_PHB_PORT(pnum) ((pnum) + 2)
+#define P7IOC_CI_UPSTREAM_PORT 0
+#define P7IOC_CI_RGC_PORT 1
+
+/* Other random chip registers */
+#define P7IOC_CHIP_FENCE_SHADOW 0x3ec010
+#define P7IOC_CHIP_FENCE_WOF 0x3ec018
+#define P7IOC_CCRR 0x3e1c00
+
+/* CI registers */
+#define P7IOC_CIn_BASE(n) (0x3d0000 | ((n) * 0x1000))
+#define P7IOC_CIn_LEM_FIR(n) (P7IOC_CIn_BASE(n) + 0x200)
+#define P7IOC_CIn_LEM_FIR_AND(n) (P7IOC_CIn_BASE(n) + 0x208)
+#define P7IOC_CIn_LEM_FIR_OR(n) (P7IOC_CIn_BASE(n) + 0x210)
+#define P7IOC_CIn_LEM_ERR_MASK(n) (P7IOC_CIn_BASE(n) + 0x218)
+#define P7IOC_CIn_LEM_ERR_MASK_AND(n) (P7IOC_CIn_BASE(n) + 0x220)
+#define P7IOC_CIn_LEM_ERR_MASK_OR(n) (P7IOC_CIn_BASE(n) + 0x228)
+
+/*
+ * PHB registers
+ */
+
+/* PHB Fundamental register set A */
+#define PHB_BUID 0x100
+#define PHB_BUID_LSI_MASK PPC_BITMASK(7,15)
+#define PHB_BUID_LSI_LSH PPC_BITLSHIFT(15)
+#define PHB_BUID_MSI_MASK PPC_BITMASK(23,31)
+#define PHB_BUID_MSI_LSH PPC_BITLSHIFT(31)
+#define PHB_DMA_CHAN_STATUS 0x110
+#define PHB_CPU_LOADSTORE_STATUS 0x120
+#define PHB_CONFIG_DATA 0x130
+#define PHB_LOCK0 0x138
+#define PHB_CONFIG_ADDRESS 0x140
+#define PHB_CA_ENABLE PPC_BIT(0)
+#define PHB_CA_BUS_MASK PPC_BITMASK(4,11)
+#define PHB_CA_BUS_LSH PPC_BITLSHIFT(11)
+#define PHB_CA_DEV_MASK PPC_BITMASK(12,16)
+#define PHB_CA_DEV_LSH PPC_BITLSHIFT(16)
+#define PHB_CA_FUNC_MASK PPC_BITMASK(17,19)
+#define PHB_CA_FUNC_LSH PPC_BITLSHIFT(19)
+#define PHB_CA_REG_MASK PPC_BITMASK(20,31)
+#define PHB_CA_REG_LSH PPC_BITLSHIFT(31)
+#define PHB_LOCK1 0x148
+#define PHB_PHB2_CONFIG 0x160
+#define PHB_PHB2C_64B_TCE_EN PPC_BIT(2)
+#define PHB_PHB2C_32BIT_MSI_EN PPC_BIT(8)
+#define PHB_PHB2C_IO_EN PPC_BIT(12)
+#define PHB_PHB2C_64BIT_MSI_EN PPC_BIT(14)
+#define PHB_PHB2C_M32_EN PPC_BIT(16)
+#define PHB_IO_BASE_ADDR 0x170
+#define PHB_IO_BASE_MASK 0x178
+#define PHB_IO_START_ADDR 0x180
+#define PHB_M32_BASE_ADDR 0x190
+#define PHB_M32_BASE_MASK 0x198
+#define PHB_M32_START_ADDR 0x1a0
+#define PHB_M64_UPPER_BITS 0x1f0
+#define PHB_TCE_KILL 0x210
+#define PHB_TCEKILL_PAIR PPC_BIT(0)
+#define PHB_TCEKILL_ADDR_MASK PPC_BITMASK(16,59)
+#define PHB_TCE_PREFETCH 0x218
+#define PHB_IODA_ADDR 0x220
+#define PHB_IODA_AD_AUTOINC PPC_BIT(0)
+#define PHB_IODA_AD_TSEL_MASK PPC_BITMASK(11,15)
+#define PHB_IODA_AD_TSEL_LSH PPC_BITLSHIFT(15)
+#define PHB_IODA_AD_TADR_MASK PPC_BITMASK(48,63)
+#define PHB_IODA_AD_TADR_LSH PPC_BITLSHIFT(63)
+#define PHB_IODA_DATA0 0x228
+#define PHB_IODA_DATA1 0x230
+#define PHB_LOCK2 0x240
+#define PHB_XIVE_UPDATE 0x248
+#define PHB_PHB2_GEN_CAP 0x250
+#define PHB_PHB2_TCE_CAP 0x258
+#define PHB_PHB2_IRQ_CAP 0x260
+#define PHB_PHB2_EEH_CAP 0x268
+#define PHB_PAPR_ERR_INJ_CONTROL 0x2b0
+#define PHB_PAPR_ERR_INJ_ADDR 0x2b8
+#define PHB_PAPR_ERR_INJ_MASK 0x2c0
+#define PHB_ETU_ERR_SUMMARY 0x2c8
+
+/* UTL registers */
+#define UTL_SYS_BUS_CONTROL 0x400
+#define UTL_STATUS 0x408
+#define UTL_SYS_BUS_AGENT_STATUS 0x410
+#define UTL_SYS_BUS_AGENT_ERR_SEVERITY 0x418
+#define UTL_SYS_BUS_AGENT_IRQ_EN 0x420
+#define UTL_SYS_BUS_BURST_SZ_CONF 0x440
+#define UTL_REVISION_ID 0x448
+#define UTL_OUT_POST_HDR_BUF_ALLOC 0x4c0
+#define UTL_OUT_POST_DAT_BUF_ALLOC 0x4d0
+#define UTL_IN_POST_HDR_BUF_ALLOC 0x4e0
+#define UTL_IN_POST_DAT_BUF_ALLOC 0x4f0
+#define UTL_OUT_NP_BUF_ALLOC 0x500
+#define UTL_IN_NP_BUF_ALLOC 0x510
+#define UTL_PCIE_TAGS_ALLOC 0x520
+#define UTL_GBIF_READ_TAGS_ALLOC 0x530
+#define UTL_PCIE_PORT_CONTROL 0x540
+#define UTL_PCIE_PORT_STATUS 0x548
+#define UTL_PCIE_PORT_ERROR_SEV 0x550
+#define UTL_PCIE_PORT_IRQ_EN 0x558
+#define UTL_RC_STATUS 0x560
+#define UTL_RC_ERR_SEVERITY 0x568
+#define UTL_RC_IRQ_EN 0x570
+#define UTL_EP_STATUS 0x578
+#define UTL_EP_ERR_SEVERITY 0x580
+#define UTL_EP_ERR_IRQ_EN 0x588
+#define UTL_PCI_PM_CTRL1 0x590
+#define UTL_PCI_PM_CTRL2 0x598
+#define UTL_GP_CTL1 0x5a0
+#define UTL_GP_CTL2 0x5a8
+
+/* PCI-E Stack registers */
+#define PHB_PCIE_SYSTEM_CONFIG 0x600
+#define PHB_PCIE_BUS_NUMBER 0x608
+#define PHB_PCIE_SYSTEM_TEST 0x618
+#define PHB_PCIE_LINK_MANAGEMENT 0x630
+#define PHB_PCIE_DLP_TRAIN_CTL 0x640
+#define PHB_PCIE_DLP_TCTX_DISABLE PPC_BIT(1)
+#define PHB_PCIE_DLP_TCRX_DISABLED PPC_BIT(16)
+#define PHB_PCIE_DLP_TC_DL_LINKUP PPC_BIT(21)
+#define PHB_PCIE_DLP_TC_DL_PGRESET PPC_BIT(22)
+#define PHB_PCIE_DLP_TC_DL_LINKACT PPC_BIT(23)
+#define PHB_PCIE_SLOP_LOOPBACK_STATUS 0x648
+#define PHB_PCIE_AER_CONTROL 0x650
+#define PHB_PCIE_AUX_POWER_CONTROL 0x658
+#define PHB_PCIE_SLOTCTL1 0x660
+#define PHB_PCIE_SLOTCTL2 0x668
+#define PHB_PCIE_SLOTCTL2_SLOTWAKE PPC_BIT(16)
+#define PHB_PCIE_SLOTCTL2_PWR_EN_STAT PPC_BIT(17)
+#define PHB_PCIE_SLOTCTL2_RCK_EN_STAT PPC_BIT(18)
+#define PHB_PCIE_SLOTCTL2_PERST_STAT PPC_BIT(19)
+#define PHB_PCIE_SLOTCTL2_PLED_S_MASK PPC_BITMASK(20,21)
+#define PHB_PCIE_SLOTCTL2_PLED_S_LSH PPC_BITLSHIFT(21) /* use PCIE_INDIC_* */
+#define PHB_PCIE_SLOTCTL2_ALED_S_MASK PPC_BITMASK(22,23)
+#define PHB_PCIE_SLOTCTL2_ALED_S_LSH PPC_BITLSHIFT(23)
+#define PHB_PCIE_SLOTCTL2_PRSTN_STAT PPC_BIT(24)
+#define PHB_PCIE_SLOTCTL2_PWRFLT_STAT PPC_BIT(25)
+#define PHB_PCIE_UTL_CONFIG 0x670
+#define PHB_PCIE_DLP_CONTROL 0x678
+#define PHB_PCIE_UTL_ERRLOG1 0x680
+#define PHB_PCIE_UTL_ERRLOG2 0x688
+#define PHB_PCIE_UTL_ERRLOG3 0x690
+#define PHB_PCIE_UTL_ERRLOG4 0x698
+#define PHB_PCIE_DLP_ERRLOG1 0x6a0
+#define PHB_PCIE_DLP_ERRLOG2 0x6a8
+#define PHB_PCIE_UTL_ERR_INJECT 0x6c0
+#define PHB_PCIE_TLDLP_ERR_INJECT 0x6c8
+#define PHB_PCIE_STRAPPING 0x700
+
+/* Fundamental register set B */
+#define PHB_VERSION 0x800
+#define PHB_RESET 0x808
+#define PHB_CONTROL 0x810
+#define PHB_AIB_RX_CRED_INIT_TIMER 0x818
+#define PHB_AIB_RX_CMD_CRED 0x820
+#define PHB_AIB_RX_DATA_CRED 0x828
+#define PHB_AIB_TX_CMD_CRED 0x830
+#define PHB_AIB_TX_DATA_CRED 0x838
+#define PHB_AIB_TX_CHAN_MAPPING 0x840
+#define PHB_AIB_TX_CRED_SYNC_CTRL 0x848
+#define PHB_LEGACY_CTRL 0x850
+#define PHB_AIB_TAG_ENABLE 0x858
+#define PHB_AIB_FENCE_CTRL 0x860
+#define PHB_TCE_TAG_ENABLE 0x868
+#define PHB_TCE_WATERMARK 0x870
+#define PHB_TIMEOUT_CTRL1 0x878
+#define PHB_TIMEOUT_CTRL2 0x880
+#define PHB_QUIESCE_DMA_G 0x888
+#define PHB_AIB_TAG_STATUS 0x900
+#define PHB_TCE_TAG_STATUS 0x908
+
+/* FIR & Error registers */
+#define PHB_LEM_FIR_ACCUM 0xc00
+#define PHB_LEM_FIR_AND_MASK 0xc08
+#define PHB_LEM_FIR_OR_MASK 0xc10
+#define PHB_LEM_ERROR_MASK 0xc18
+#define PHB_LEM_ERROR_AND_MASK 0xc20
+#define PHB_LEM_ERROR_OR_MASK 0xc28
+#define PHB_LEM_ACTION0 0xc30
+#define PHB_LEM_ACTION1 0xc38
+#define PHB_LEM_WOF 0xc40
+#define PHB_ERR_STATUS 0xc80
+#define PHB_ERR1_STATUS 0xc88
+#define PHB_ERR_INJECT 0xc90
+#define PHB_ERR_LEM_ENABLE 0xc98
+#define PHB_ERR_IRQ_ENABLE 0xca0
+#define PHB_ERR_FREEZE_ENABLE 0xca8
+#define PHB_ERR_AIB_FENCE_ENABLE 0xcb0
+#define PHB_ERR_LOG_0 0xcc0
+#define PHB_ERR_LOG_1 0xcc8
+#define PHB_ERR_STATUS_MASK 0xcd0
+#define PHB_ERR1_STATUS_MASK 0xcd8
+
+#define PHB_OUT_ERR_STATUS 0xd00
+#define PHB_OUT_ERR1_STATUS 0xd08
+#define PHB_OUT_ERR_INJECT 0xd10
+#define PHB_OUT_ERR_LEM_ENABLE 0xd18
+#define PHB_OUT_ERR_IRQ_ENABLE 0xd20
+#define PHB_OUT_ERR_FREEZE_ENABLE 0xd28
+#define PHB_OUT_ERR_AIB_FENCE_ENABLE 0xd30
+#define PHB_OUT_ERR_LOG_0 0xd40
+#define PHB_OUT_ERR_LOG_1 0xd48
+#define PHB_OUT_ERR_STATUS_MASK 0xd50
+#define PHB_OUT_ERR1_STATUS_MASK 0xd58
+
+#define PHB_INA_ERR_STATUS 0xd80
+#define PHB_INA_ERR1_STATUS 0xd88
+#define PHB_INA_ERR_INJECT 0xd90
+#define PHB_INA_ERR_LEM_ENABLE 0xd98
+#define PHB_INA_ERR_IRQ_ENABLE 0xda0
+#define PHB_INA_ERR_FREEZE_ENABLE 0xda8
+#define PHB_INA_ERR_AIB_FENCE_ENABLE 0xdb0
+#define PHB_INA_ERR_LOG_0 0xdc0
+#define PHB_INA_ERR_LOG_1 0xdc8
+#define PHB_INA_ERR_STATUS_MASK 0xdd0
+#define PHB_INA_ERR1_STATUS_MASK 0xdd8
+
+#define PHB_INB_ERR_STATUS 0xe00
+#define PHB_INB_ERR1_STATUS 0xe08
+#define PHB_INB_ERR_INJECT 0xe10
+#define PHB_INB_ERR_LEM_ENABLE 0xe18
+#define PHB_INB_ERR_IRQ_ENABLE 0xe20
+#define PHB_INB_ERR_FREEZE_ENABLE 0xe28
+#define PHB_INB_ERR_AIB_FENCE_ENABLE 0xe30
+#define PHB_INB_ERR_LOG_0 0xe40
+#define PHB_INB_ERR_LOG_1 0xe48
+#define PHB_INB_ERR_STATUS_MASK 0xe50
+#define PHB_INB_ERR1_STATUS_MASK 0xe58
+
+/* Performance monitor & Debug registers */
+#define PHB_TRACE_CONTROL 0xf80
+#define PHB_PERFMON_CONFIG 0xf88
+#define PHB_PERFMON_CTR0 0xf90
+#define PHB_PERFMON_CTR1 0xf98
+#define PHB_PERFMON_CTR2 0xfa0
+#define PHB_PERFMON_CTR3 0xfa8
+#define PHB_HOTPLUG_OVERRIDE 0xfb0
+
+/*
+ * IODA tables
+ */
+
+#define IODA_TBL_HRT 0
+#define IODA_TBL_LIST 1
+#define IODA_TBL_LXIVT 2
+#define IODA_TBL_MIST 3
+#define IODA_TBL_MXIVT 4
+#define IODA_TBL_MVT 5
+#define IODA_TBL_PELTM 6
+#define IODA_TBL_PESTA 7
+#define IODA_TBL_PESTB 8
+#define IODA_TBL_TVT 9
+#define IODA_TBL_TCAM 10
+#define IODA_TBL_TDR 11
+#define IODA_TBL_PELTV 12
+#define IODA_TBL_M64BT 16
+#define IODA_TBL_IODT 17
+#define IODA_TBL_M32DT 18
+#define IODA_TBL_M64DT 19
+#define IODA_TBL_PEEV 20
+
+/* L/M XIVT */
+#define IODA_XIVT_SERVER_MASK PPC_BITMASK(8,23)
+#define IODA_XIVT_SERVER_LSH PPC_BITLSHIFT(23)
+#define IODA_XIVT_PRIORITY_MASK PPC_BITMASK(24,31)
+#define IODA_XIVT_PRIORITY_LSH PPC_BITLSHIFT(31)
+#define IODA_XIVT_PENUM_MASK PPC_BITMASK(41,47)
+#define IODA_XIVT_PENUM_LSH PPC_BITLSHIFT(47)
+#define IODA_XIVT_HUBNUM_MASK PPC_BITMASK(58,59)
+#define IODA_XIVT_HUBNUM_LSH PPC_BITLSHIFT(59)
+
+/* M64BT */
+#define IODA_M64BT_ENABLE PPC_BIT(0)
+#define IODA_M64BT_BASE_MASK PPC_BITMASK(8,31)
+#define IODA_M64BT_BASE_LSH PPC_BITLSHIFT(31)
+#define IODA_M64BT_MASK_MASK PPC_BITMASK(40,63)
+#define IODA_M64BT_MASK_LSH PPC_BITLSHIFT(63)
+
+/* IODT/M32DT/M64DX */
+#define IODA_XXDT_PE_MASK PPC_BITMASK(0,6)
+#define IODA_XXDT_PE_LSH PPC_BITLSHIFT(6)
+
+/* PELTM */
+#define IODA_PELTM_BUS_MASK PPC_BITMASK(0,7)
+#define IODA_PELTM_BUS_LSH PPC_BITLSHIFT(7)
+#define IODA_PELTM_DEV_MASK PPC_BITMASK(8,12)
+#define IODA_PELTM_DEV_LSH PPC_BITLSHIFT(12)
+#define IODA_PELTM_FUNC_MASK PPC_BITMASK(13,15)
+#define IODA_PELTM_FUNC_LSH PPC_BITLSHIFT(15)
+#define IODA_PELTM_BUS_VALID_MASK PPC_BITMASK(16,18)
+#define IODA_PELTM_BUS_VALID_LSH PPC_BITLSHIFT(18)
+#define IODA_BUS_VALID_ANY 0
+#define IODA_BUS_VALID_3_BITS 2
+#define IODA_BUS_VALID_4_BITS 3
+#define IODA_BUS_VALID_5_BITS 4
+#define IODA_BUS_VALID_6_BITS 5
+#define IODA_BUS_VALID_7_BITS 6
+#define IODA_BUS_VALID_ALL 7
+#define IODA_PELTM_DEV_VALID PPC_BIT(19)
+#define IODA_PELTM_FUNC_VALID PPC_BIT(20)
+
+/* TVT */
+#define IODA_TVT0_TABLE_ADDR_MASK PPC_BITMASK(0,47)
+#define IODA_TVT0_TABLE_ADDR_LSH PPC_BITLSHIFT(47)
+#define IODA_TVT0_BUS_VALID_MASK PPC_BITMASK(48,50)
+#define IODA_TVT0_BUS_VALID_LSH PPC_BITLSHIFT(50)
+#define IODA_TVT0_TCE_TABLE_SIZE_MASK PPC_BITMASK(51,55)
+#define IODA_TVT0_TCE_TABLE_SIZE_LSH PPC_BITLSHIFT(55)
+#define IODA_TVT0_BUS_NUM_MASK PPC_BITMASK(56,63)
+#define IODA_TVT0_BUS_NUM_LSH PPC_BITLSHIFT(63)
+#define IODA_TVT1_DEV_VALID PPC_BIT(2)
+#define IODA_TVT1_DEV_NUM_MASK PPC_BITMASK(3,7)
+#define IODA_TVT1_DEV_NUM_LSH PPC_BITLSHIFT(7)
+#define IODA_TVT1_HUB_NUM_MASK PPC_BITMASK(10,11)
+#define IODA_TVT1_HUB_NUM_LSH PPC_BITLSHIFT(11)
+#define IODA_TVT1_FUNC_VALID PPC_BIT(12)
+#define IODA_TVT1_FUNC_NUM_MASK PPC_BITMASK(13,15)
+#define IODA_TVT1_FUNC_NUM_LSH PPC_BITLSHIFT(15)
+#define IODA_TVT1_IO_PSIZE_MASK PPC_BITMASK(19,23)
+#define IODA_TVT1_IO_PSIZE_LSH PPC_BITLSHIFT(23)
+#define IODA_TVT1_PE_NUM_MASK PPC_BITMASK(57,63)
+#define IODA_TVT1_PE_NUM_LSH PPC_BITLSHIFT(63)
+
+/* MVT */
+#define IODA_MVT_VALID PPC_BIT(0)
+#define IODA_MVT_BUS_VALID_MASK PPC_BITMASK(21,23)
+#define IODA_MVT_BUS_VALID_LSH PPC_BITLSHIFT(23)
+#define IODA_MVT_BUS_NUM_MASK PPC_BITMASK(24,31)
+#define IODA_MVT_BUS_NUM_LSH PPC_BITLSHIFT(31)
+#define IODA_MVT_PE_NUM_MASK PPC_BITMASK(41,47)
+#define IODA_MVT_PE_NUM_LSH PPC_BITLSHIFT(47)
+#define IODA_MVT_DEV_VALID PPC_BIT(50)
+#define IODA_MVT_DEV_NUM_MASK PPC_BITMASK(51,55)
+#define IODA_MVT_DEV_NUM_LSH PPC_BITLSHIFT(55)
+#define IODA_MVT_FUNC_VALID PPC_BIT(60)
+#define IODA_MVT_FUNC_NUM_MASK PPC_BITMASK(61,63)
+#define IODA_MVT_FUNC_NUM_LSH PPC_BITLSHIFT(63)
+
+/* PESTA */
+#define IODA_PESTA_MMIO_FROZEN PPC_BIT(0)
+#define IODA_PESTA_MMIO_CAUSE PPC_BIT(2)
+#define IODA_PESTA_CFG_READ PPC_BIT(3)
+#define IODA_PESTA_CFG_WRITE PPC_BIT(4)
+#define IODA_PESTA_TTYPE_MASK PPC_BITMASK(5,7)
+#define IODA_PESTA_TTYPE_LSH PPC_BITLSHIFT(7)
+#define PESTA_TTYPE_DMA_WRITE 0
+#define PESTA_TTYPE_MSI 1
+#define PESTA_TTYPE_DMA_READ 2
+#define PESTA_TTYPE_DMA_READ_RESP 3
+#define PESTA_TTYPE_MMIO_LOAD 4
+#define PESTA_TTYPE_MMIO_STORE 5
+#define PESTA_TTYPE_OTHER 7
+#define IODA_PESTA_CA_RETURN PPC_BIT(8)
+#define IODA_PESTA_UTL_RTOS_TIMEOUT PPC_BIT(8) /* Same bit as CA return */
+#define IODA_PESTA_UR_RETURN PPC_BIT(9)
+#define IODA_PESTA_UTL_NONFATAL PPC_BIT(10)
+#define IODA_PESTA_UTL_FATAL PPC_BIT(11)
+#define IODA_PESTA_TAG_REUSE_ERROR PPC_BIT(12)
+#define IODA_PESTA_PARITY_UE PPC_BIT(13)
+#define IODA_PESTA_UTL_CORRECTABLE PPC_BIT(14)
+#define IODA_PESTA_UTL_INTERRUPT PPC_BIT(15)
+#define IODA_PESTA_MMIO_XLATE PPC_BIT(16)
+#define IODA_PESTA_IODA_ERROR PPC_BIT(16) /* Same bit as MMIO xlate */
+#define IODA_PESTA_TVT_EXT_ERROR PPC_BIT(17)
+#define IODA_PESTA_TCE_PAGE_FAULT PPC_BIT(18)
+#define IODA_PESTA_TCE_ACCESS_FAULT PPC_BIT(19)
+#define IODA_PESTA_DMA_RESP_TIMEOUT PPC_BIT(20)
+#define IODA_PESTA_AIB_SIZE_INVALID PPC_BIT(21)
+#define IODA_PESTA_LEM_BIT_MASK PPC_BITMASK(26,31)
+#define IODA_PESTA_LEM_BIT_LSH PPC_BITLSHIFT(31)
+#define IODA_PESTA_RID_MASK PPC_BITMASK(32,47)
+#define IODA_PESTA_RID_LSH PPC_BITLSHIFT(47)
+#define IODA_PESTA_MSI_DATA_MASK PPC_BITMASK(48,63)
+#define IODA_PESTA_MSI_DATA_LSH PPC_BITLSHIFT(63)
+
+/* PESTB */
+#define IODA_PESTB_DMA_STOPPED PPC_BIT(0)
+#define IODA_PESTB_FAIL_ADDR_MASK PPC_BITMASK(3,63)
+#define IODA_PESTB_FAIL_ADDR_LSH PPC_BITLSHIFT(63)
+
+#endif /* __P7IOC_REGS_H */
diff --git a/include/p7ioc.h b/include/p7ioc.h
new file mode 100644
index 0000000..70c174e
--- /dev/null
+++ b/include/p7ioc.h
@@ -0,0 +1,431 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __P7IOC_H
+#define __P7IOC_H
+
+#include <cec.h>
+#include <pci.h>
+#include <lock.h>
+
+#include <ccan/container_of/container_of.h>
+
+/*
+ * Memory windows and BUID assignment
+ *
+ * - GX BAR assignment
+ *
+ * I don't know of any spec here, so we're going to mimmic what
+ * OPAL seems to be doing:
+ *
+ * - BAR 0 : 32M, disabled. We just leave it alone.
+ * - BAR 1 : 8G, enabled. Appears to correspond to the MMIO
+ * space of the IOC itself and the PCI IO space
+ * - BAR 2: 128G,
+ * - BAR 3: 128G,
+ * - BAR 4: 128G, all 3 contiguous, forming a single 368G region
+ * and is used for M32 and M64 PHB windows.
+ *
+ * - Memory map
+ *
+ * MWIN1 = BAR1 (8G)
+ * MWIN2 = BAR2,3,4 (384G)
+ *
+ * MWIN2 is divided into 6 * 4G regions for use by M32's (*) and
+ * 6 * 32G regions for use by M64's.
+ *
+ * (*) The M32 will typically be configured to only 2G or so, however
+ * the OS is in control of that setting, and since we have to reserve
+ * a power of two, we reserve the whole 4G.
+ *
+ * - RGC registers: MWIN1 + 0x00000000
+ * - PHBn IO space: MWIN1 + 0x01000000 + n * 0x00800000 (8M each)
+ * - PHBn M32 : MWIN2 + n * 0x1_00000000 (4G each)
+ * - PHBn M64 : MWIN2 + (n + 1) * 0x8_00000000 (32G each)
+ *
+ * - BUID map. The RGC has interrupts, each PHB has then its own
+ * interrupts (errors etc...), 4 LSIs and 256 LSIs so
+ * respectively 1 BUID for self, 1 for LSIs and 16 for LSIs
+ *
+ * We keep all BUIDs below 0x10 reserved. They will be used for things
+ * like the PSI controller, the NX unit, etc.. in the P7 chip.
+ *
+ * RGC : 0x010
+ * PHBn LSI : 0x040 + n * 0x40 ( 1 BUID)
+ * PHBn MSI : 0x060 + n * 0x40 (0x10 BUIDs)
+ *
+ * -> For routing, each PHB gets a block of 0x40 BUIDs:
+ *
+ * from 0x40 * (n + 1) to 0x7f * (n + 1)
+ */
+
+/* Some definitions resulting from the above description
+ *
+ * Note: A better approach might be to read the GX BAR content
+ * and isolate the biggest contiguous windows. From there
+ * we could divide things algorithmically and thus be
+ * less sensitive to a change in the memory map by the FSP
+ */
+#define MWIN1_SIZE 0x200000000ul /* MWIN1 is 8G */
+#define MWIN2_SIZE 0x6000000000ul /* MWIN2 is 384G */
+#define PHB_IO_OFFSET 0x01000000ul /* Offset of PHB IO space in MWIN1 */
+#define PHB_IO_SIZE 0x00800000ul
+#define PHB_M32_OFFSET 0x0ul /* Offset of PHB M32 space in MWIN2 */
+#define PHB_M32_SIZE 0x100000000ul
+#define PHB_M64_OFFSET 0x800000000ul /* Offset of PHB M64 space in MWIN2 */
+#define PHB_M64_SIZE 0x800000000ul
+#define RGC_BUID_OFFSET 0x10 /* Offset of RGC BUID */
+#define PHB_BUID_OFFSET 0x40 /* Offset of PHB BUID blocks */
+#define PHB_BUID_SIZE 0x40 /* Size of PHB BUID blocks */
+#define PHB_BUID_LSI_OFFSET 0x00 /* Offset of LSI in PHB BUID block */
+#define PHB_BUID_MSI_OFFSET 0x20 /* Offset of MSI in PHB BUID block */
+#define PHB_BUID_MSI_SIZE 0x10 /* Size of PHB MSI BUID block */
+
+#define PHBn_IO_BASE(n) (PHB_IO_OFFSET + (n) * PHB_IO_SIZE)
+#define PHBn_M32_BASE(n) (PHB_M32_OFFSET + (n) * PHB_M32_SIZE)
+#define PHBn_M64_BASE(n) (PHB_M64_OFFSET + (n) * PHB_M64_SIZE)
+#define PHBn_BUID_BASE(n) (PHB_BUID_OFFSET + (n) * PHB_BUID_SIZE)
+
+#define BUID_TO_PHB(buid) (((buid) - PHB_BUID_OFFSET) / PHB_BUID_SIZE)
+
+/* p7ioc has 6 PHBs */
+#define P7IOC_NUM_PHBS 6
+
+/* M32 window setting at boot:
+ *
+ * To allow for DMA, we need to split the 32-bit PCI address space between
+ * MMIO and DMA. For now, we use a 2G/2G split with MMIO at the top.
+ *
+ * Note: The top 64K of the M32 space are used by MSIs. This is not
+ * visible here but need to be conveyed to the OS one way or another
+ *
+ * Note2: The space reserved in the system address space for M32 is always
+ * 4G. That we chose to use a smaller portion of it is not relevant to
+ * the upper levels. To keep things consistent, the offset we apply to
+ * the window start is also applied on the host side.
+ */
+#define M32_PCI_START 0x80000000
+#define M32_PCI_SIZE 0x80000000
+
+/* PHB registers exist in both a hard coded space and a programmable
+ * AIB space. We program the latter to the values recommended in the
+ * documentation:
+ *
+ * 0x80000 + n * 0x10000
+ */
+#define PHBn_ASB_BASE(n) (((n) << 16))
+#define PHBn_ASB_SIZE 0x10000ul
+#define PHBn_AIB_BASE(n) (0x80000ul + ((n) << 16))
+#define PHBn_AIB_SIZE 0x10000ul
+
+/*
+ * LSI interrupts
+ *
+ * The LSI interrupt block supports 8 interrupts. 4 of them are the
+ * standard PCIe INTA..INTB. The rest is for additional functions
+ * of the PHB
+ */
+#define PHB_LSI_PCIE_INTA 0
+#define PHB_LSI_PCIE_INTB 1
+#define PHB_LSI_PCIE_INTC 2
+#define PHB_LSI_PCIE_INTD 3
+#define PHB_LSI_PCIE_HOTPLUG 4
+#define PHB_LSI_PCIE_PERFCTR 5
+#define PHB_LSI_PCIE_UNUSED 6
+#define PHB_LSI_PCIE_ERROR 7
+
+/*
+ * State structure for a PHB on P7IOC
+ */
+
+/*
+ * The PHB State structure is essentially used during PHB reset
+ * or recovery operations to indicate that the PHB cannot currently
+ * be used for normal operations.
+ *
+ * Some states involve waiting for the timebase to reach a certain
+ * value. In which case the field "delay_tgt_tb" is set and the
+ * state machine will be run from the "state_poll" callback.
+ *
+ * At IPL time, we call this repeatedly during the various sequences
+ * however under OS control, this will require a change in API.
+ *
+ * Fortunately, the OPAL API for slot power & reset are not currently
+ * used by Linux, so changing them isn't going to be an issue. The idea
+ * here is that some of these APIs will return a positive integer when
+ * needing such a delay to proceed. The OS will then be required to
+ * call a new function opal_poll_phb() after that delay. That function
+ * will potentially return a new delay, or OPAL_SUCCESS when the original
+ * operation has completed successfully. If the operation has completed
+ * with an error, then opal_poll_phb() will return that error.
+ *
+ * Note: Should we consider also returning optionally some indication
+ * of what operation is in progress for OS debug/diag purposes ?
+ *
+ * Any attempt at starting a new "asynchronous" operation while one is
+ * already in progress will result in an error.
+ *
+ * Internally, this is represented by the state being P7IOC_PHB_STATE_FUNCTIONAL
+ * when no operation is in progress, which it reaches at the end of the
+ * boot time initializations. Any attempt at performing a slot operation
+ * on a PHB in that state will change the state to the corresponding
+ * operation state machine. Any attempt while not in that state will
+ * return an error.
+ *
+ * Some operations allow for a certain amount of retries, this is
+ * provided for by the "retries" structure member for use by the state
+ * machine as it sees fit.
+ */
+enum p7ioc_phb_state {
+ /* First init state */
+ P7IOC_PHB_STATE_UNINITIALIZED,
+
+ /* During PHB HW inits */
+ P7IOC_PHB_STATE_INITIALIZING,
+
+ /* Set if the PHB is for some reason unusable */
+ P7IOC_PHB_STATE_BROKEN,
+
+ /* Set if the PHB is fenced due to an error */
+ P7IOC_PHB_STATE_FENCED,
+
+ /* PHB turned off by FSP (no clocks) */
+ P7IOC_PHB_STATE_OFF,
+
+ /* Slot Power up state machine */
+ P7IOC_PHB_STATE_SPUP_STABILIZE_DELAY, /* Step 3 Delay 2s */
+ P7IOC_PHB_STATE_SPUP_SLOT_STATUS, /* Step 4 waiting for status */
+
+ /* Slot Power down state machine */
+ P7IOC_PHB_STATE_SPDOWN_STABILIZE_DELAY, /* Step 2 Delay 2s */
+ P7IOC_PHB_STATE_SPDOWN_SLOT_STATUS, /* Step 3 waiting for status */
+
+ /* Fundamental reset sequence */
+ P7IOC_PHB_STATE_FRESET_DISABLE_LINK, /* Disable link training */
+ P7IOC_PHB_STATE_FRESET_ASSERT_DELAY, /* Delay on fundamental reset assert */
+ P7IOC_PHB_STATE_FRESET_DEASSERT_DELAY, /* Delay on fundamental reset deassert */
+ P7IOC_PHB_STATE_FRESET_WAIT_LINK, /* Wait for link up */
+
+ /* Hot Reset sequence */
+ P7IOC_PHB_STATE_HRESET_DISABLE_LINK, /* Disable Link training */
+ P7IOC_PHB_STATE_HRESET_ASSERT, /* Hot reset assert */
+ P7IOC_PHB_STATE_HRESET_DELAY, /* Hot reset delay */
+ P7IOC_PHB_STATE_HRESET_ENABLE_LINK, /* Enable Link training */
+ P7IOC_PHB_STATE_HRESET_WAIT_LINK, /* Wait link traing */
+
+ /* Normal PHB functional state */
+ P7IOC_PHB_STATE_FUNCTIONAL,
+};
+
+/*
+ * In order to support error detection and recovery on different
+ * types of IOCs (e.g. P5IOC, P7IOC, P8IOC), the best bet would
+ * be make the implementation to be 2 layers: OPAL layer and IOC
+ * layer. The OPAL layer just handles the general information and
+ * IOC layer should process much more detailed information, which
+ * is sensitive to itself.
+ */
+#define P7IOC_ERR_SRC_NONE 0
+#define P7IOC_ERR_SRC_EI 1
+#define P7IOC_ERR_SRC_RGC 2
+#define P7IOC_ERR_SRC_BI_UP 3
+#define P7IOC_ERR_SRC_BI_DOWN 4
+#define P7IOC_ERR_SRC_CI_P0 5
+#define P7IOC_ERR_SRC_CI_P1 6
+#define P7IOC_ERR_SRC_CI_P2 7
+#define P7IOC_ERR_SRC_CI_P3 8
+#define P7IOC_ERR_SRC_CI_P4 9
+#define P7IOC_ERR_SRC_CI_P5 10
+#define P7IOC_ERR_SRC_CI_P6 11
+#define P7IOC_ERR_SRC_CI_P7 12
+#define P7IOC_ERR_SRC_PHB0 13
+#define P7IOC_ERR_SRC_PHB1 14
+#define P7IOC_ERR_SRC_PHB2 15
+#define P7IOC_ERR_SRC_PHB3 16
+#define P7IOC_ERR_SRC_PHB4 17
+#define P7IOC_ERR_SRC_PHB5 18
+#define P7IOC_ERR_SRC_MISC 19
+#define P7IOC_ERR_SRC_I2C 20
+#define P7IOC_ERR_SRC_LAST 21
+
+#define P7IOC_ERR_CLASS_NONE 0
+#define P7IOC_ERR_CLASS_GXE 1
+#define P7IOC_ERR_CLASS_PLL 2
+#define P7IOC_ERR_CLASS_RGA 3
+#define P7IOC_ERR_CLASS_PHB 4
+#define P7IOC_ERR_CLASS_ER 5
+#define P7IOC_ERR_CLASS_INF 6
+#define P7IOC_ERR_CLASS_MAL 7
+#define P7IOC_ERR_CLASS_LAST 8
+
+/*
+ * P7IOC error descriptor. For errors from PHB and PE, they
+ * will be cached to the corresponding PHBs. However, the
+ * left errors (e.g. EI, CI Port0/1) will be cached to the
+ * IOC directly.
+ */
+struct p7ioc_err {
+ uint32_t err_src;
+ uint32_t err_class;
+ uint32_t err_bit;
+};
+
+struct p7ioc;
+
+#define P7IOC_PHB_CFG_USE_ASB 1 /* ASB to access PCI-CFG */
+#define P7IOC_PHB_CFG_BLOCKED 2 /* PCI-CFG blocked except 0 */
+
+struct p7ioc_phb {
+ uint8_t index; /* 0..5 index inside p7ioc */
+ uint8_t gen;
+ uint32_t flags;
+ void *regs_asb;
+ void *regs; /* AIB regs */
+ struct lock lock;
+ uint32_t buid_lsi;
+ uint32_t buid_msi;
+ uint64_t io_base;
+ uint64_t m32_base;
+ uint64_t m64_base;
+ enum p7ioc_phb_state state;
+ uint64_t delay_tgt_tb;
+ uint64_t retries;
+ int64_t ecap; /* cached PCI-E cap offset */
+ int64_t aercap; /* cached AER ecap offset */
+ uint64_t lxive_cache[8];
+ uint64_t mxive_cache[256];
+ uint64_t mve_cache[256];
+ uint64_t peltm_cache[128];
+ uint64_t peltv_lo_cache[128];
+ uint64_t peltv_hi_cache[128];
+ uint64_t tve_lo_cache[128];
+ uint64_t tve_hi_cache[128];
+ uint64_t iod_cache[128];
+ uint64_t m32d_cache[128];
+ uint64_t m64b_cache[16];
+ uint64_t m64d_cache[128];
+ bool err_pending;
+ struct p7ioc_err err;
+ struct p7ioc *ioc;
+ struct phb phb;
+};
+
+static inline struct p7ioc_phb *phb_to_p7ioc_phb(struct phb *phb)
+{
+ return container_of(phb, struct p7ioc_phb, phb);
+}
+
+static inline bool p7ioc_phb_err_pending(struct p7ioc_phb *p)
+{
+ return p->err_pending;
+}
+
+static inline void p7ioc_phb_set_err_pending(struct p7ioc_phb *p, bool pending)
+{
+ if (!pending) {
+ p->err.err_src = P7IOC_ERR_SRC_NONE;
+ p->err.err_class = P7IOC_ERR_CLASS_NONE;
+ p->err.err_bit = -1;
+ }
+
+ p->err_pending = pending;
+}
+
+/*
+ * State structure for P7IOC IO HUB
+ */
+struct p7ioc {
+ /* Device node */
+ struct dt_node *dt_node;
+
+ /* MMIO regs */
+ void *regs;
+
+ /* Main MMIO window from GX for registers & PCI IO space */
+ uint64_t mmio1_win_start;
+ uint64_t mmio1_win_size;
+
+ /* Secondary MMIO window for PCI MMIO space */
+ uint64_t mmio2_win_start;
+ uint64_t mmio2_win_size;
+
+ /* BUID base for the PHB. This does include the top bits
+ * (chip, GX bus ID, etc...). This is initialized from the
+ * SPIRA. It does not contain the offset 0x10 for RGC
+ * interrupts.
+ *
+ * The OPAL-defined "interrupt-base" property will contain
+ * the RGC BUID, not this base value, since this is the real
+ * starting point of interrupts for the IOC and we don't want
+ * to cover the BUID 0..f gap which is reserved for P7 on-chip
+ * interrupt sources.
+ */
+ uint32_t buid_base;
+ uint32_t rgc_buid;
+
+ /* XIVT cache for RGC interrupts */
+ uint64_t xive_cache[16];
+ bool err_pending;
+ struct p7ioc_err err;
+
+ /* PHB array & presence detect */
+ struct p7ioc_phb phbs[P7IOC_NUM_PHBS];
+ uint8_t phb_pdt;
+
+ struct io_hub hub;
+};
+
+static inline struct p7ioc *iohub_to_p7ioc(struct io_hub *hub)
+{
+ return container_of(hub, struct p7ioc, hub);
+}
+
+static inline bool p7ioc_err_pending(struct p7ioc *ioc)
+{
+ return ioc->err_pending;
+}
+
+static inline void p7ioc_set_err_pending(struct p7ioc *ioc, bool pending)
+{
+ if (!pending) {
+ ioc->err.err_src = P7IOC_ERR_SRC_NONE;
+ ioc->err.err_class = P7IOC_ERR_CLASS_NONE;
+ ioc->err.err_bit = -1;
+ }
+
+ ioc->err_pending = pending;
+}
+
+static inline bool p7ioc_phb_enabled(struct p7ioc *ioc, unsigned int phb)
+{
+ return !!(ioc->phb_pdt & (0x80 >> phb));
+}
+
+extern int64_t p7ioc_inits(struct p7ioc *ioc);
+
+extern void p7ioc_phb_setup(struct p7ioc *ioc, uint8_t index);
+extern int64_t p7ioc_phb_init(struct p7ioc_phb *p);
+
+extern bool p7ioc_check_LEM(struct p7ioc *ioc, uint16_t *pci_error_type,
+ uint16_t *severity);
+extern int64_t p7ioc_phb_get_xive(struct p7ioc_phb *p, uint32_t isn,
+ uint16_t *server, uint8_t *prio);
+extern int64_t p7ioc_phb_set_xive(struct p7ioc_phb *p, uint32_t isn,
+ uint16_t server, uint8_t prio);
+extern void p7ioc_reset(struct io_hub *hub);
+extern void p7ioc_phb_reset(struct phb *phb);
+
+#endif /* __P7IOC_H */
diff --git a/include/pci-cfg.h b/include/pci-cfg.h
new file mode 100644
index 0000000..7c98f3f
--- /dev/null
+++ b/include/pci-cfg.h
@@ -0,0 +1,524 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * PCI Configuration space definitions
+ */
+#ifndef __PCI_CFG_H
+#define __PCI_CFG_H
+
+/* Common cfg space header */
+#define PCI_CFG_VENDOR_ID 0x0000
+#define PCI_CFG_DEVICE_ID 0x0002
+#define PCI_CFG_CMD 0x0004
+#define PCI_CFG_CMD_IO_EN 0x0001
+#define PCI_CFG_CMD_MEM_EN 0x0002
+#define PCI_CFG_CMD_BUS_MASTER_EN 0x0004
+#define PCI_CFG_CMD_PERR_RESP 0x0040
+#define PCI_CFG_CMD_SERR_EN 0x0100
+#define PCI_CFG_CMD_INTx_DIS 0x0400
+#define PCI_CFG_STAT 0x0006
+#define PCI_CFG_STAT_INTx 0x0008
+#define PCI_CFG_STAT_CAP 0x0010
+#define PCI_CFG_STAT_MDATAPERR 0x0100
+#define PCI_CFG_STAT_SENT_TABORT 0x0800
+#define PCI_CFG_STAT_RECV_TABORT 0x1000
+#define PCI_CFG_STAT_RECV_MABORT 0x2000
+#define PCI_CFG_STAT_SENT_SERR 0x4000
+#define PCI_CFG_STAT_RECV_PERR 0x8000
+#define PCI_CFG_REV_ID 0x0008
+#define PCI_CFG_CLAS_CODE 0x0009
+#define PCI_CFG_CACHE_LINE_SIZE 0x000c
+#define PCI_CFG_LAT_TIMER 0x000d
+#define PCI_CFG_HDR_TYPE 0x000e
+#define PCI_CFG_BIST 0x000f
+#define PCI_CFG_BAR0 0x0010
+#define PCI_CFG_BAR_TYPE_MASK 0x00000001
+#define PCI_CFG_BAR_TYPE_MEM 0x00000000
+#define PCI_CFG_BAR_TYPE_IO 0x00000001
+#define PCI_CFG_BAR_MEM64 0x00000004
+#define PCI_CFG_BAR_MEM_PREFETCH 0x00000008
+#define PCI_CFG_BAR1 0x0014
+
+/* Type 0 fields */
+#define PCI_CFG_BAR2 0x0018
+#define PCI_CFG_BAR3 0x001c
+#define PCI_CFG_BAR4 0x0020
+#define PCI_CFG_BAR5 0x0024
+#define PCI_CFG_CARDBUS_CIS 0x0028
+#define PCI_CFG_SUBSYS_VENDOR_ID 0x002c
+#define PCI_CFG_SUBSYS_ID 0x002e
+#define PCI_CFG_ROMBAR 0x0030
+#define PCI_CFG_CAP 0x0034
+#define PCI_CFG_INT_LINE 0x003c
+#define PCI_CFG_INT_PIN 0x003d
+#define PCI_CFG_INT_MIN_GNT 0x003e
+#define PCI_CFG_INT_MAX_LAT 0x003f
+
+/* Type 1 fields */
+#define PCI_CFG_PRIMARY_BUS 0x0018
+#define PCI_CFG_SECONDARY_BUS 0x0019
+#define PCI_CFG_SUBORDINATE_BUS 0x001a
+#define PCI_CFG_SEC_LAT_TIMER 0x001b
+#define PCI_CFG_IO_BASE 0x001c
+#define PCI_CFG_IO_LIMIT 0x001d
+#define PCI_CFG_SECONDARY_STATUS 0x001e
+#define PCI_CFG_MEM_BASE 0x0020
+#define PCI_CFG_MEM_LIMIT 0x0022
+#define PCI_CFG_PREF_MEM_BASE 0x0024
+#define PCI_CFG_PREF_MEM_LIMIT 0x0026
+#define PCI_CFG_PREF_MEM_BASE_U32 0x0028
+#define PCI_CFG_PREF_MEM_LIMIT_U32 0x002c
+#define PCI_CFG_IO_BASE_U16 0x0030
+#define PCI_CFG_IO_LIMIT_U16 0x0032
+#define PCI_CFG_BR_CAP 0x0034 /* Same as type 0 */
+#define PCI_CFG_BR_ROMBAR 0x0038 /* Different from type 0 */
+#define PCI_CFG_BR_INT_LINE 0x003c /* Same as type 0 */
+#define PCI_CFG_BR_INT_PIN 0x003d /* Same as type 0 */
+#define PCI_CFG_BRCTL 0x003e
+#define PCI_CFG_BRCTL_PERR_RESP_EN 0x0001
+#define PCI_CFG_BRCTL_SERR_EN 0x0002
+#define PCI_CFG_BRCTL_ISA_EN 0x0004
+#define PCI_CFG_BRCTL_VGA_EN 0x0008
+#define PCI_CFG_BRCTL_VGA_16BIT 0x0010
+#define PCI_CFG_BRCTL_MABORT_REPORT 0x0020
+#define PCI_CFG_BRCTL_SECONDARY_RESET 0x0040
+#define PCI_CFG_BRCTL_FAST_BACK2BACK 0x0080
+#define PCI_CFG_BRCTL_PRI_DISC_TIMER 0x0100
+#define PCI_CFG_BRCTL_SEC_DISC_TIMER 0x0200
+#define PCI_CFG_BRCTL_DISC_TIMER_STAT 0x0400
+#define PCI_CFG_BRCTL_DISC_TIMER_SERR 0x0800
+
+/*
+ * Standard capabilties
+ */
+#define PCI_CFG_CAP_ID 0
+#define PCI_CFG_CAP_NEXT 1
+
+/* PCI bridge subsystem ID capability */
+#define PCI_CFG_CAP_ID_SUBSYS_VID 0x0d
+#define PCICAP_SUBSYS_VID_VENDOR 4
+#define PCICAP_SUBSYS_VID_DEVICE 6
+
+/* PCI Express capability */
+#define PCI_CFG_CAP_ID_EXP 0x10
+/* PCI Express capability fields */
+#define PCICAP_EXP_CAPABILITY_REG 0x02
+#define PCICAP_EXP_CAP_VERSION_MASK 0x000f
+#define PCICAP_EXP_CAP_VERSION_LSH 0
+#define PCICAP_EXP_CAP_TYPE_MASK 0x00f0
+#define PCICAP_EXP_CAP_TYPE_LSH 4
+#define PCIE_TYPE_ENDPOINT 0x0
+#define PCIE_TYPE_LEGACY 0x1
+#define PCIE_TYPE_ROOT_PORT 0x4
+#define PCIE_TYPE_SWITCH_UPPORT 0x5
+#define PCIE_TYPE_SWITCH_DNPORT 0x6
+#define PCIE_TYPE_PCIE_TO_PCIX 0x7
+#define PCIE_TYPE_PCIX_TO_PCIE 0x8
+#define PCIE_TYPE_RC_INTEGRATED 0x9
+#define PCIE_TYPE_RC_EVT_COLL 0xa
+#define PCICAP_EXP_CAP_SLOT 0x0100
+#define PCICAP_EXP_CAP_MSI_NUM_MASK 0x3e00
+#define PCICAP_EXP_CAP_MSI_NUM_LSH 9
+#define PCICAP_EXP_CAP_TCS_ROUTING 0x4000
+#define PCICAP_EXP_DEVCAP 0x04
+#define PCICAP_EXP_DEVCAP_MPSS_MASK 0x00000007
+#define PCICAP_EXP_DEVCAP_MPSS_LSH 0
+#define PCIE_MPSS_128 0
+#define PCIE_MPSS_256 1
+#define PCIE_MPSS_512 2
+#define PCIE_MPSS_1024 3
+#define PCIE_MPSS_2048 4
+#define PCIE_MPSS_4096 5
+#define PCICAP_EXP_DEVCAP_PHANT_MASK 0x00000018
+#define PCICAP_EXP_DEVCAP_PHANT_LSH 3
+#define PCIE_PHANTOM_NONE 0
+#define PCIE_PHANTOM_1MSB 1
+#define PCIE_PHANTOM_2MSB 2
+#define PCIE_PHANTOM_3MSB 3
+#define PCICAP_EXP_DEVCAP_EXTTAG 0x00000020
+#define PCICAP_EXP_DEVCAP_L0SL_MASK 0x000001c0
+#define PCICAP_EXP_DEVCAP_L0SL_LSH 6
+#define PCIE_L0SL_MAX_64NS 0
+#define PCIE_L0SL_MAX_128NS 1
+#define PCIE_L0SL_MAX_256NS 2
+#define PCIE_L0SL_MAX_512NS 3
+#define PCIE_L0SL_MAX_1US 4
+#define PCIE_L0SL_MAX_2US 5
+#define PCIE_L0SL_MAX_4US 6
+#define PCIE_L0SL_MAX_NO_LIMIT 7
+#define PCICAP_EXP_DEVCAP_L1L_MASK 0x00000e00
+#define PCICAP_EXP_DEVCAP_L1L_LSH 9
+#define PCIE_L1L_MAX_1US 0
+#define PCIE_L1L_MAX_2US 1
+#define PCIE_L1L_MAX_4US 2
+#define PCIE_L1L_MAX_8US 3
+#define PCIE_L1L_MAX_16US 4
+#define PCIE_L1L_MAX_32US 5
+#define PCIE_L1L_MAX_64US 6
+#define PCIE_L1L_MAX_NO_LIMIT 7
+#define PCICAP_EXP_ROLE_BASED_ERR 0x00008000
+#define PCICAP_EXP_DEVCAP_PWRVAL_MASK 0x03fc0000
+#define PCICAP_EXP_DEVCAP_PWRVAL_LSH 18
+#define PCICAP_EXP_DEVCAP_PWRSCA_MASK 0x0c000000
+#define PCICAP_EXP_DEVCAP_PWRSCA_LSH 26
+#define PCIE_SLOT_PWR_SCALE_1x 0
+#define PCIE_SLOT_PWR_SCALE_0d1x 1
+#define PCIE_SLOT_PWR_SCALE_0d01x 2
+#define PCIE_SLOT_PWR_SCALE_0d001x 3
+#define PCICAP_EXP_DEVCAP_FUNC_RESET 0x10000000
+#define PCICAP_EXP_DEVCTL 0x08
+#define PCICAP_EXP_DEVCTL_CE_REPORT 0x0001
+#define PCICAP_EXP_DEVCTL_NFE_REPORT 0x0002
+#define PCICAP_EXP_DEVCTL_FE_REPORT 0x0004
+#define PCICAP_EXP_DEVCTL_UR_REPORT 0x0008
+#define PCICAP_EXP_DEVCTL_RELAX_ORD 0x0010
+#define PCICAP_EXP_DEVCTL_MPS_MASK 0x00e0
+#define PCICAP_EXP_DEVCTL_MPS_LSH 5
+#define PCIE_MPS_128B 0
+#define PCIE_MPS_256B 1
+#define PCIE_MPS_512B 2
+#define PCIE_MPS_1024B 3
+#define PCIE_MPS_2048B 4
+#define PCIE_MPS_4096B 5
+#define PCICAP_EXP_DEVCTL_EXT_TAG 0x0100
+#define PCICAP_EXP_DEVCTL_PHANTOM 0x0200
+#define PCICAP_EXP_DEVCTL_AUX_POW_PM 0x0400
+#define PCICAP_EXP_DEVCTL_NO_SNOOP 0x0800
+#define PCICAP_EXP_DEVCTL_MRRS_MASK 0x7000
+#define PCICAP_EXP_DEVCTL_MRRS_LSH 12
+#define PCIE_MRSS_128B 0
+#define PCIE_MRSS_256B 1
+#define PCIE_MRSS_512B 2
+#define PCIE_MRSS_1024B 3
+#define PCIE_MRSS_2048B 4
+#define PCIE_MRSS_4096B 5
+#define PCICAP_EXP_DEVCTL_PCIX_RETRY 0x8000 /* PCIe - PCIX bridges only */
+#define PCICAP_EXP_DEVCTL_FUNC_RESET 0x8000 /* all others */
+#define PCICAP_EXP_DEVSTAT 0x0a
+#define PCICAP_EXP_DEVSTAT_CE 0x0001
+#define PCICAP_EXP_DEVSTAT_NFE 0x0002
+#define PCICAP_EXP_DEVSTAT_FE 0x0004
+#define PCICAP_EXP_DEVSTAT_UE 0x0008
+#define PCICAP_EXP_DEVSTAT_AUX_POW 0x0010
+#define PCICAP_EXP_DEVSTAT_TPEND 0x0020
+#define PCICAP_EXP_LCAP 0x0c
+#define PCICAP_EXP_LCAP_MAXSPD_MASK 0x0000000f
+#define PCICAP_EXP_LCAP_MAXSPD_LSH 0
+#define PCIE_LSPEED_VECBIT_0 0x1
+#define PCIE_LSPEED_VECBIT_1 0x2
+#define PCIE_LSPEED_VECBIT_2 0x3
+#define PCIE_LSPEED_VECBIT_3 0x4
+#define PCIE_LSPEED_VECBIT_4 0x5
+#define PCIE_LSPEED_VECBIT_5 0x6
+#define PCIE_LSPEED_VECBIT_6 0x7
+#define PCICAP_EXP_LCAP_MAXWDTH_MASK 0x000003f0
+#define PCICAP_EXP_LCAP_MAXWDTH_LSH 4
+#define PCIE_LWIDTH_1X 1
+#define PCIE_LWIDTH_2X 2
+#define PCIE_LWIDTH_4X 4
+#define PCIE_LWIDTH_8X 8
+#define PCIE_LWIDTH_12X 12
+#define PCIE_LWIDTH_16X 16
+#define PCIE_LWIDTH_32X 32
+#define PCICAP_EXP_LCAP_ASPM_L0S 0x00000400
+#define PCICAP_EXP_LCAP_ASPM_L1 0x00000800
+#define PCICAP_EXP_LCAP_L0S_EXLT_MASK 0x00007000
+#define PCICAP_EXP_LCAP_L0S_EXLT_LSH 12
+#define PCIE_L0S_EXLT_LESS_64NS 0
+#define PCIE_L0S_EXLT_64NS_128NS 1
+#define PCIE_L0S_EXLT_128NS_256NS 2
+#define PCIE_L0S_EXLT_256NS_512NS 3
+#define PCIE_L0S_EXLT_512NS_1US 4
+#define PCIE_L0S_EXLT_1US_2US 5
+#define PCIE_L0S_EXLT_2US_4US 6
+#define PCIE_L0S_EXLT_MORE_4US 7
+#define PCICAP_EXP_LCAP_L1_EXLT_MASK 0x00038000
+#define PCICAP_EXP_LCAP_L1_EXLT_LSH 15
+#define PCIE_L1_EXLT_LESS_1US 0
+#define PCIE_L1_EXLT_1US_2US 1
+#define PCIE_L1_EXLT_2US_4US 2
+#define PCIE_L1_EXLT_4US_8US 3
+#define PCIE_L1_EXLT_8US_16US 4
+#define PCIE_L1_EXLT_16US_32US 5
+#define PCIE_L1_EXLT_32US_64US 6
+#define PCIE_L1_EXLT_MORE_64US 7
+#define PCICAP_EXP_LCAP_CLK_PM 0x00040000
+#define PCICAP_EXP_LCAP_SURP_DWN_ERR 0x00080000
+#define PCICAP_EXP_LCAP_DL_ACT_REP 0x00100000
+#define PCICAP_EXP_LCAP_LNKBWDTH_NOTF 0x00200000
+#define PCICAP_EXP_LCAP_ASPM_OPT_CMPL 0x00400000
+#define PCICAP_EXP_LCAP_PORTNUM_MASK 0xff000000
+#define PCICAP_EXP_LCAP_PORTNUM_LSH 24
+#define PCICAP_EXP_LCTL 0x10
+#define PCICAP_EXP_LCTL_ASPM_L0S 0x0001
+#define PCICAP_EXP_LCTL_ASPM_L1 0x0002
+#define PCICAP_EXP_LCTL_RCB 0x0008 /* RO on root ports */
+#define PCICAP_EXP_LCTL_LINK_DIS 0x0010
+#define PCICAP_EXP_LCTL_LINK_RETRAIN 0x0020
+#define PCICAP_EXP_LCTL_COMMON_CLK 0x0040
+#define PCICAP_EXP_LCTL_EXT_SYNCH 0x0080
+#define PCICAP_EXP_LCTL_CLOCK_PM 0x0100
+#define PCICAP_EXP_LCTL_HW_AWIDTH_DIS 0x0200
+#define PCICAP_EXP_LCTL_LBWM_INT_EN 0x0400
+#define PCICAP_EXP_LCTL_LAWD_INT_EN 0x0800
+#define PCICAP_EXP_LSTAT 0x12
+#define PCICAP_EXP_LSTAT_SPEED_MASK 0x000f
+#define PCICAP_EXP_LSTAT_SPEED_LSH 0 /* use PCIE_LSPEED_* consts */
+#define PCICAP_EXP_LSTAT_WIDTH_MASK 0x03f0
+#define PCICAP_EXP_LSTAT_WIDTH_LSH 4 /* use PCIE_LWIDTH_* consts */
+#define PCICAP_EXP_LSTAT_TRAINING 0x0800
+#define PCICAP_EXP_LSTAT_SLOTCLKCFG 0x1000
+#define PCICAP_EXP_LSTAT_DLLL_ACT 0x2000
+#define PCICAP_EXP_LSTAT_LBWM_STAT 0x4000
+#define PCICAP_EXP_LSTAT_LAWS_STAT 0x8000
+#define PCICAP_EXP_SLOTCAP 0x14
+#define PCICAP_EXP_SLOTCAP_ATTNB 0x00000001
+#define PCICAP_EXP_SLOTCAP_PWCTRL 0x00000002
+#define PCICAP_EXP_SLOTCAP_MRLSENS 0x00000004
+#define PCICAP_EXP_SLOTCAP_ATTNI 0x00000008
+#define PCICAP_EXP_SLOTCAP_PWRI 0x00000010
+#define PCICAP_EXP_SLOTCAP_HPLUG_SURP 0x00000020
+#define PCICAP_EXP_SLOTCAP_HPLUG_CAP 0x00000040
+#define PCICAP_EXP_SLOTCAP_SPLVA_MASK 0x00007f80
+#define PCICAP_EXP_SLOTCAP_SPLLVA_LSH 7
+#define PCICAP_EXP_SLOTCAP_SPLSC_MASK 0x00018000
+#define PCICAP_EXP_SLOTCAP_SPLSC_LSH 15
+#define PCICAP_EXP_SLOTCAP_EIP 0x00020000
+#define PCICAP_EXP_SLOTCAP_NO_CMDCOMP 0x00040000
+#define PCICAP_EXP_SLOTCAP_PSLOT_MASK 0xfff80000
+#define PCICAP_EXP_SLOTCAP_PSLOT_LSH 19
+#define PCICAP_EXP_SLOTCTL 0x18
+#define PCICAP_EXP_SLOTCTL_ATTNB 0x0001
+#define PCICAP_EXP_SLOTCTL_PFLT 0x0002
+#define PCICAP_EXP_SLOTCTL_MRLSENSE 0x0004
+#define PCICAP_EXP_SLOTCTL_PDETECT 0x0008
+#define PCICAP_EXP_SLOTCTL_CMDCOMPINT 0x0010
+#define PCICAP_EXP_SLOTCTL_HPINT 0x0020
+#define PCICAP_EXP_SLOTCTL_ATTNI_MASK 0x00c0
+#define PCICAP_EXP_SLOTCTL_ATTNI_LSH 6
+#define PCIE_INDIC_ON 1
+#define PCIE_INDIC_BLINK 2
+#define PCIE_INDIC_OFF 3
+#define PCICAP_EXP_SLOTCTL_PWRI_MASK 0x0300
+#define PCICAP_EXP_SLOTCTL_PWRI_LSH 8 /* Use PCIE_INDIC_* consts */
+#define PCICAP_EXP_SLOTCTL_PWRCTLR 0x0400
+#define PCICAP_EXP_SLOTCTL_EIC 0x0800
+#define PCICAP_EXP_SLOTCTL_DLLSTCHG 0x1000
+#define PCICAP_EXP_SLOTSTAT 0x1a
+#define PCICAP_EXP_SLOTSTAT_ATTNBCH 0x0001
+#define PCICAP_EXP_SLOTSTAT_PWRFLTCH 0x0002
+#define PCICAP_EXP_SLOTSTAT_MRLSENSCH 0x0004
+#define PCICAP_EXP_SLOTSTAT_PDETECTCH 0x0008
+#define PCICAP_EXP_SLOTSTAT_CMDCOMPCH 0x0010
+#define PCICAP_EXP_SLOTSTAT_MRLSENSST 0x0020
+#define PCICAP_EXP_SLOTSTAT_PDETECTST 0x0040
+#define PCICAP_EXP_SLOTSTAT_EIS 0x0080
+#define PCICAP_EXP_SLOTSTAT_DLLSTCH 0x0100
+#define PCICAP_EXP_RC 0x1c
+#define PCICAP_EXP_RC_SYSERR_ON_CE 0x0001
+#define PCICAP_EXP_RC_SYSERR_ON_NFE 0x0002
+#define PCICAP_EXP_RC_SYSERR_ON_FE 0x0004
+#define PCICAP_EXP_RC_PME_INT_EN 0x0008
+#define PCICAP_EXP_RC_CRS_VISIBLE 0x0010
+#define PCICAP_EXP_RCAP 0x1e
+#define PCICAP_EXP_RCAP_CRS_VISIBLE 0x0001
+#define PCICAP_EXP_RSTAT 0x20
+#define PCICAP_EXP_RSTAT_PME_RID_MASK 0x0000ffff
+#define PCICAP_EXP_RSTAT_PME_RID_LSH 0
+#define PCICAP_EXP_RSTAT_PME_STATUS 0x00010000
+#define PCICAP_EXP_RSTAT_PME_PENDING 0x00020000
+#define PCIECAP_EXP_DCAP2 0x24
+#define PCICAP_EXP_DCAP2_CMPTOUT_MASK 0x0000000f
+#define PCICAP_EXP_DCAP2_CMPTOUT_LSH 0
+#define PCICAP_EXP_DCAP2_CMPTOUT_DIS 0x00000010
+#define PCICAP_EXP_DCAP2_ARI_FWD 0x00000020
+#define PCICAP_EXP_DCAP2_ATOMIC_RTE 0x00000040
+#define PCICAP_EXP_DCAP2_ATOMIC32 0x00000080
+#define PCICAP_EXP_DCAP2_ATOMIC64 0x00000100
+#define PCICAP_EXP_DCAP2_CAS128 0x00000200
+#define PCICAP_EXP_DCAP2_NORO_PRPR 0x00000400
+#define PCICAP_EXP_DCAP2_LTR 0x00000800
+#define PCICAP_EXP_DCAP2_TPHCOMP 0x00001000
+#define PCICAP_EXP_DCAP2_TPHCOMP_EXT 0x00002000
+#define PCICAP_EXP_DCAP2_OBFF_MSG 0x00040000
+#define PCICAP_EXP_DCAP2_OBFF_WAKE 0x00080000
+#define PCICAP_EXP_DCAP2_EXTFMT 0x00100000
+#define PCICAP_EXP_DCAP2_EETLP_PFX 0x00200000
+#define PCICAP_EXP_DCAP2_MAXEETP_MASK 0x00c00000
+#define PCICAP_EXP_DCAP2_MAXEETP_LSH 22
+#define PCIE_EETLPP_1 1
+#define PCIE_EETLPP_2 2
+#define PCIE_EETLPP_3 3
+#define PCIE_EETLPP_4 0
+#define PCICAP_EXP_DCTL2 0x28
+#define PCICAP_EXP_DCTL2_CMPTOUT_MASK 0x000f
+#define PCICAP_EXP_DCTL2_CMPTOUT_LSH 0
+#define PCICAP_EXP_DCTL2_CMPTOUT_DIS 0x0010
+#define PCICAP_EXP_DCTL2_ARI_FWD 0x0020
+#define PCICAP_EXP_DCTL2_ATOMIC_REQ 0x0040
+#define PCICAP_EXP_DCTL2_ATOMIC_EGBLK 0x0080
+#define PCICAP_EXP_DCTL2_IDO_REQ 0x0100
+#define PCICAP_EXP_DCTL2_IDO_COMPL 0x0200
+#define PCICAP_EXP_DCTL2_LTR 0x0400
+#define PCICAP_EXP_DCTL2_OBFF_MASK 0x6000
+#define PCICAP_EXP_DCTL2_OBFF_LSH 13
+#define PCIE_OBFF_MODE_DISABLED 0
+#define PCIE_OBFF_MODE_MSG_A 1
+#define PCIE_OBFF_MODE_MSG_B 2
+#define PCIE_OBFF_MODE_WAKE 3
+#define PCICAP_EXP_DCTL2_EETLPP_BLK 0x8000
+#define PCICAP_EXP_DSTA2 0x2a
+#define PCICAP_EXP_LCAP2 0x2c
+#define PCICAP_EXP_LCAP2_SP_2d5GTs 0x00000002
+#define PCICAP_EXP_LCAP2_SP_5d0GTs 0x00000004
+#define PCICAP_EXP_LCAP2_SP_8d0GTs 0x00000008
+#define PCICAP_EXP_LCAP2_XLINK 0x00000100
+#define PCICAP_EXP_LCTL2 0x30
+#define PCICAP_EXP_LCTL2_TLSPD_MASK 0x000f
+#define PCICAP_EXP_LCTL2_TLSPD_LSH 0 /* use PCIE_LSPEED_ consts */
+#define PCICAP_EXP_LCTL2_ENTER_COMPL 0x0010
+#define PCICAP_EXP_LCTL2_HWAUTSPDIS 0x0020
+#define PCICAP_EXP_LCTL2_SEL_DEEMPH 0x0040
+#define PCICAP_EXP_LCTL2_XMTMARG_MASK 0x0380
+#define PCICAP_EXP_LCTL2_XMTMARG_LSH 7
+#define PCICAP_EXP_LCTL2_ENTER_MCOMPL 0x0400
+#define PCICAP_EXP_LCTL2_COMPL_SOS 0x0800
+#define PCICAP_EXP_LCTL2_CMPPDEM_MASK 0xf000
+#define PCICAP_EXP_LCTL2_CMPPDEM_LSH 12
+#define PCICAP_EXP_LSTA2 0x32
+#define PCICAP_EXP_LSTA2_DEMPH_LVL 0x0001
+#define PCICAP_EXP_LSTA2_EQ_COMPLETE 0x0002
+#define PCICAP_EXP_LSTA2_EQ_PH1_OK 0x0004
+#define PCICAP_EXP_LSTA2_EQ_PH2_OK 0x0008
+#define PCICAP_EXP_LSTA2_EQ_PH3_OK 0x0010
+#define PCICAP_EXP_LSTA2_LINK_EQ_REQ 0x0020
+#define PCICAP_EXP_SCAP2 0x34
+#define PCICAP_EXP_SCTL2 0x38
+#define PCICAP_EXP_SSTA2 0x3a
+
+/*
+ * PCI-E Extended capabilties
+ */
+#define PCI_CFG_ECAP_START 0x100
+#define PCI_CFG_ECAP_ID_MASK 0x0000ffff
+#define PCI_CFG_ECAP_ID_LSH 0
+#define PCI_CFG_ECAP_VERS_MASK 0x000f0000
+#define PCI_CFG_ECAP_VERS_LSH 16
+#define PCI_CFG_ECAP_NEXT_MASK 0xfff00000
+#define PCI_CFG_ECAP_NEXT_LSH 20
+
+/* AER Ext. Capability */
+#define PCIECAP_ID_AER 0x0001
+#define PCIECAP_AER_UE_STATUS 0x04
+#define PCIECAP_AER_UE_DLP 0x00000010
+#define PCIECAP_AER_UE_SURPRISE_DOWN 0x00000020
+#define PCIECAP_AER_UE_POISON_TLP 0x00001000
+#define PCIECAP_AER_UE_FLOW_CTL_PROT 0x00002000
+#define PCIECAP_AER_UE_COMPL_TIMEOUT 0x00004000
+#define PCIECAP_AER_UE_COMPL_ABORT 0x00008000
+#define PCIECAP_AER_UE_UNEXP_COMPL 0x00010000
+#define PCIECAP_AER_UE_RECV_OVFLOW 0x00020000
+#define PCIECAP_AER_UE_MALFORMED_TLP 0x00040000
+#define PCIECAP_AER_UE_ECRC 0x00080000
+#define PCIECAP_AER_UE_UNSUPP_REQ 0x00100000
+#define PCIECAP_AER_UE_ACS_VIOLATION 0x00200000
+#define PCIECAP_AER_UE_INTERNAL 0x00400000
+#define PCIECAP_AER_UE_MC_BLKD_TLP 0x00800000
+#define PCIECAP_AER_UE_ATOMIC_EGBLK 0x01000000
+#define PCIECAP_AER_UE_TLP_PRFX_BLK 0x02000000
+#define PCIECAP_AER_UE_MASK 0x08
+#define PCIECAP_AER_UE_MASK_DLLP 0x00000010
+#define PCIECAP_AER_UE_MASK_SURPRISE_DOWN 0x00000020
+#define PCIECAP_AER_UE_MASK_POISON_TLP 0x00001000
+#define PCIECAP_AER_UE_MASK_FLOW_CTL_PROT 0x00002000
+#define PCIECAP_AER_UE_MASK_COMPL_TIMEOUT 0x00004000
+#define PCIECAP_AER_UE_MASK_COMPL_ABORT 0x00008000
+#define PCIECAP_AER_UE_MASK_UNEXP_COMPL 0x00010000
+#define PCIECAP_AER_UE_MASK_RECV_OVFLOW 0x00020000
+#define PCIECAP_AER_UE_MASK_MALFORMED_TLP 0x00040000
+#define PCIECAP_AER_UE_MASK_ECRC 0x00080000
+#define PCIECAP_AER_UE_MASK_UNSUPP_REQ 0x00100000
+#define PCIECAP_AER_UE_SEVERITY 0x0c
+#define PCIECAP_AER_UE_SEVERITY_DLLP 0x00000010
+#define PCIECAP_AER_UE_SEVERITY_SURPRISE_DOWN 0x00000020
+#define PCIECAP_AER_UE_SEVERITY_POISON_TLP 0x00001000
+#define PCIECAP_AER_UE_SEVERITY_FLOW_CTL_PROT 0x00002000
+#define PCIECAP_AER_UE_SEVERITY_COMPL_TIMEOUT 0x00004000
+#define PCIECAP_AER_UE_SEVERITY_COMPL_ABORT 0x00008000
+#define PCIECAP_AER_UE_SEVERITY_UNEXP_COMPL 0x00010000
+#define PCIECAP_AER_UE_SEVERITY_RECV_OVFLOW 0x00020000
+#define PCIECAP_AER_UE_SEVERITY_MALFORMED_TLP 0x00040000
+#define PCIECAP_AER_UE_SEVERITY_ECRC 0x00080000
+#define PCIECAP_AER_UE_SEVERITY_UNSUPP_REQ 0x00100000
+#define PCIECAP_AER_UE_SEVERITY_INTERNAL 0x00400000
+#define PCIECAP_AER_CE_STATUS 0x10
+#define PCIECAP_AER_CE_RECVR_ERR 0x00000001
+#define PCIECAP_AER_CE_BAD_TLP 0x00000040
+#define PCIECAP_AER_CE_BAD_DLLP 0x00000080
+#define PCIECAP_AER_CE_REPLAY_ROLLVR 0x00000100
+#define PCIECAP_AER_CE_REPLAY_TMR_TO 0x00001000
+#define PCIECAP_AER_CE_ADV_NONFATAL 0x00002000
+#define PCIECAP_AER_CE_CORTD_INTERNAL 0x00004000
+#define PCIECAP_AER_CE_HDR_LOG_OVFL 0x00008000
+#define PCIECAP_AER_CE_MASK 0x14
+#define PCIECAP_AER_CE_MASK_RECVR_ERR 0x00000001
+#define PCIECAP_AER_CE_MASK_BAD_TLP 0x00000040
+#define PCIECAP_AER_CE_MASK_BAD_DLLP 0x00000080
+#define PCIECAP_AER_CE_MASK_REPLAY_ROLLVR 0x00000100
+#define PCIECAP_AER_CE_MASK_REPLAY_TMR_TO 0x00001000
+#define PCIECAP_AER_CE_MASK_ADV_NONFATAL 0x00002000
+#define PCIECAP_AER_CE_MASK_CORTD_INTERNAL 0x00004000
+#define PCIECAP_AER_CE_MASK_HDR_LOG_OVFL 0x00008000
+#define PCIECAP_AER_CAPCTL 0x18
+#define PCIECAP_AER_CAPCTL_FPTR_MASK 0x0000001f
+#define PCIECAP_AER_CAPCTL_FPTR_LSH 0
+#define PCIECAP_AER_CAPCTL_ECRCG_CAP 0x00000020
+#define PCIECAP_AER_CAPCTL_ECRCG_EN 0x00000040
+#define PCIECAP_AER_CAPCTL_ECRCC_CAP 0x00000080
+#define PCIECAP_AER_CAPCTL_ECRCC_EN 0x00000100
+#define PCIECAP_AER_CAPCTL_MHREC_CAP 0x00000200
+#define PCIECAP_AER_CAPCTL_MHREC_EN 0x00000400
+#define PCIECAP_AER_CAPCTL_TLPPL_PR 0x00000800
+#define PCIECAP_AER_HDR_LOG0 0x1c
+#define PCIECAP_AER_HDR_LOG1 0x20
+#define PCIECAP_AER_HDR_LOG2 0x24
+#define PCIECAP_AER_HDR_LOG3 0x28
+#define PCIECAP_AER_RERR_CMD 0x2c
+#define PCIECAP_AER_RERR_CMD_FE 0x00000001
+#define PCIECAP_AER_RERR_CMD_NFE 0x00000002
+#define PCIECAP_AER_RERR_CMD_CE 0x00000004
+#define PCIECAP_AER_RERR_STA 0x30
+#define PCIECAP_AER_RERR_STA_CORR 0x00000001
+#define PCIECAP_AER_RERR_STA_MCORR 0x00000002
+#define PCIECAP_AER_RERR_STA_FNF 0x00000004
+#define PCIECAP_AER_RERR_STA_MFNF 0x00000008
+#define PCIECAP_AER_RERR_F_UFATAL 0x00000010
+#define PCIECAP_AER_RERR_NFE 0x00000020
+#define PCIECAP_AER_RERR_FE 0x00000040
+#define PCIECAP_AER_RERR_MSINO_MASK 0xf8000000
+#define PCIECAP_AER_RERR_MSINO_LSH 27
+#define PCIECAP_AER_SRCID 0x34
+#define PCIECAP_AER_SRCID_CORR_MASK 0x0000ffff
+#define PCIECAP_AER_SRCID_CORR_LSH 0
+#define PCIECAP_AER_SRCID_FNF_MASK 0xffff0000
+#define PCIECAP_AER_SRCID_FNF_LSH 16
+#define PCIECAP_AER_TLP_PFX_LOG0 0x38
+#define PCIECAP_AER_TLP_PFX_LOG1 0x3c
+#define PCIECAP_AER_TLP_PFX_LOG2 0x40
+#define PCIECAP_AER_TLP_PFX_LOG3 0x44
+
+#endif /* __PCI_CFG_H */
diff --git a/include/pci.h b/include/pci.h
new file mode 100644
index 0000000..984bd38
--- /dev/null
+++ b/include/pci.h
@@ -0,0 +1,504 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PCI_H
+#define __PCI_H
+
+#include <opal.h>
+#include <device.h>
+#include <ccan/list/list.h>
+
+/* PCI Slot Info: Wired Lane Values
+ *
+ * Values 0 to 6 match slot map 1005. In case of *any* change here
+ * make sure to keep the lxvpd.c parsing code in sync *and* the
+ * corresponding label strings in pci.c
+ */
+#define PCI_SLOT_WIRED_LANES_UNKNOWN 0x00
+#define PCI_SLOT_WIRED_LANES_PCIE_X1 0x01
+#define PCI_SLOT_WIRED_LANES_PCIE_X2 0x02
+#define PCI_SLOT_WIRED_LANES_PCIE_X4 0x03
+#define PCI_SLOT_WIRED_LANES_PCIE_X8 0x04
+#define PCI_SLOT_WIRED_LANES_PCIE_X16 0x05
+#define PCI_SLOT_WIRED_LANES_PCIE_X32 0x06
+#define PCI_SLOT_WIRED_LANES_PCIX_32 0x07
+#define PCI_SLOT_WIRED_LANES_PCIX_64 0x08
+
+/* PCI Slot Info: Bus Clock Values */
+#define PCI_SLOT_BUS_CLK_RESERVED 0x00
+#define PCI_SLOT_BUS_CLK_GEN_1 0x01
+#define PCI_SLOT_BUS_CLK_GEN_2 0x02
+#define PCI_SLOT_BUS_CLK_GEN_3 0x03
+
+/* PCI Slot Info: Connector Type Values */
+#define PCI_SLOT_CONNECTOR_PCIE_EMBED 0x00
+#define PCI_SLOT_CONNECTOR_PCIE_X1 0x01
+#define PCI_SLOT_CONNECTOR_PCIE_X2 0x02
+#define PCI_SLOT_CONNECTOR_PCIE_X4 0x03
+#define PCI_SLOT_CONNECTOR_PCIE_X8 0x04
+#define PCI_SLOT_CONNECTOR_PCIE_X16 0x05
+#define PCI_SLOT_CONNECTOR_PCIE_NS 0x0E /* Non-Standard */
+
+/* PCI Slot Info: Card Description Values */
+#define PCI_SLOT_DESC_NON_STANDARD 0x00 /* Embed/Non-Standard Connector */
+#define PCI_SLOT_DESC_PCIE_FH_FL 0x00 /* Full Height, Full Length */
+#define PCI_SLOT_DESC_PCIE_FH_HL 0x01 /* Full Height, Half Length */
+#define PCI_SLOT_DESC_PCIE_HH_FL 0x02 /* Half Height, Full Length */
+#define PCI_SLOT_DESC_PCIE_HH_HL 0x03 /* Half Height, Half Length */
+
+/* PCI Slot Info: Mechanicals Values */
+#define PCI_SLOT_MECH_NONE 0x00
+#define PCI_SLOT_MECH_RIGHT 0x01
+#define PCI_SLOT_MECH_LEFT 0x02
+#define PCI_SLOT_MECH_RIGHT_LEFT 0x03
+
+/* PCI Slot Info: Power LED Control Values */
+#define PCI_SLOT_PWR_LED_CTL_NONE 0x00 /* No Control */
+#define PCI_SLOT_PWR_LED_CTL_FSP 0x01 /* FSP Controlled */
+#define PCI_SLOT_PWR_LED_CTL_KERNEL 0x02 /* Kernel Controlled */
+
+/* PCI Slot Info: ATTN LED Control Values */
+#define PCI_SLOT_ATTN_LED_CTL_NONE 0x00 /* No Control */
+#define PCI_SLOT_ATTN_LED_CTL_FSP 0x01 /* FSP Controlled */
+#define PCI_SLOT_ATTN_LED_CTL_KERNEL 0x02 /* Kernel Controlled */
+
+/* PCI Slot Entry Information */
+struct pci_slot_info {
+ uint8_t switch_id;
+ uint8_t vswitch_id;
+ uint8_t dev_id;
+ char label[9];
+ bool pluggable;
+ bool power_ctl;
+ uint8_t wired_lanes;
+ uint8_t bus_clock;
+ uint8_t connector_type;
+ uint8_t card_desc;
+ uint8_t card_mech;
+ uint8_t pwr_led_ctl;
+ uint8_t attn_led_ctl;
+ uint8_t slot_index;
+};
+
+/*
+ * While this might not be necessary in the long run, the existing
+ * Linux kernels expect us to provide a device-tree that contains
+ * a representation of all PCI devices below the host bridge. Thus
+ * we need to perform a bus scan. We don't need to assign MMIO/IO
+ * resources, but we do need to assign bus numbers in a way that
+ * is going to be compatible with the HW constraints for PE filtering
+ * that is naturally aligned power of twos for ranges below a bridge.
+ *
+ * Thus the structure pci_device is used for the tracking of the
+ * detected devices and the later generation of the device-tree.
+ *
+ * We do not keep a separate structure for a bus, however a device
+ * can have children in which case a device is a bridge.
+ *
+ * Because this is likely to change, we avoid putting too much
+ * information in that structure nor relying on it for anything
+ * else but the construction of the flat device-tree.
+ */
+struct pci_device {
+ uint16_t bdfn;
+ bool is_bridge;
+ bool is_multifunction;
+ uint8_t dev_type; /* PCIE */
+ uint32_t scan_map;
+
+ uint64_t cap_list;
+ uint32_t cap[64];
+ uint32_t mps; /* Max payload size capability */
+
+ struct pci_slot_info *slot_info;
+ struct pci_device *parent;
+ struct list_head children;
+ struct list_node link;
+};
+
+static inline void pci_set_cap(struct pci_device *pd,
+ int id, int pos, bool ext)
+{
+ if (!ext) {
+ pd->cap_list |= (0x1ul << id);
+ pd->cap[id] = pos;
+ } else {
+ pd->cap_list |= (0x1ul << (id + 32));
+ pd->cap[id + 32] = pos;
+ }
+}
+
+static inline bool pci_has_cap(struct pci_device *pd,
+ int id, bool ext)
+{
+ if (!ext)
+ return !!(pd->cap_list & (0x1ul << id));
+ else
+ return !!(pd->cap_list & (0x1ul << (id + 32)));
+}
+
+static inline int pci_cap(struct pci_device *pd,
+ int id, bool ext)
+{
+ if (!ext)
+ return pd->cap[id];
+ else
+ return pd->cap[id + 32];
+}
+
+/*
+ * When generating the device-tree, we need to keep track of
+ * the LSI mapping & swizzle it. This state structure is
+ * passed by the PHB to pci_add_nodes() and will be used
+ * internally.
+ *
+ * We assume that the interrupt parent (PIC) #address-cells
+ * is 0 and #interrupt-cells has a max value of 2.
+ */
+struct pci_lsi_state {
+#define MAX_INT_SIZE 2
+ uint32_t int_size; /* #cells */
+ uint32_t int_val[4][MAX_INT_SIZE]; /* INTA...INTD */
+ uint32_t int_parent[4];
+};
+
+/*
+ * NOTE: All PCI functions return negative OPAL error codes
+ *
+ * In addition, some functions may return a positive timeout
+ * value or some other state information, see the description
+ * of individual functions. If nothing is specified, it's
+ * just an error code or 0 (success).
+ *
+ * Functions that operate asynchronously will return a positive
+ * delay value and will require the ->poll() op to be called after
+ * that delay. ->poll() will then return success, a negative error
+ * code, or another delay.
+ *
+ * Note: If an asynchronous function returns 0, it has completed
+ * successfully and does not require a call to ->poll(). Similarly
+ * if ->poll() is called while no operation is in progress, it will
+ * simply return 0 (success)
+ *
+ * Note that all functions except ->lock() itself assume that the
+ * caller is holding the PHB lock.
+ *
+ * TODO: Add more interfaces to control things like link width
+ * reduction for power savings etc...
+ */
+
+struct phb;
+
+struct phb_ops {
+ /*
+ * Locking. This is called around OPAL accesses
+ */
+ void (*lock)(struct phb *phb);
+ void (*unlock)(struct phb *phb);
+
+ /*
+ * Config space ops
+ */
+ int64_t (*cfg_read8)(struct phb *phb, uint32_t bdfn,
+ uint32_t offset, uint8_t *data);
+ int64_t (*cfg_read16)(struct phb *phb, uint32_t bdfn,
+ uint32_t offset, uint16_t *data);
+ int64_t (*cfg_read32)(struct phb *phb, uint32_t bdfn,
+ uint32_t offset, uint32_t *data);
+ int64_t (*cfg_write8)(struct phb *phb, uint32_t bdfn,
+ uint32_t offset, uint8_t data);
+ int64_t (*cfg_write16)(struct phb *phb, uint32_t bdfn,
+ uint32_t offset, uint16_t data);
+ int64_t (*cfg_write32)(struct phb *phb, uint32_t bdfn,
+ uint32_t offset, uint32_t data);
+
+ /*
+ * Bus number selection. See pci_scan() for a description
+ */
+ uint8_t (*choose_bus)(struct phb *phb, struct pci_device *bridge,
+ uint8_t candidate, uint8_t *max_bus,
+ bool *use_max);
+
+ /*
+ * Device init method is called after a device has been detected
+ * and before probing further. It can alter things like scan_map
+ * for bridge ports etc...
+ */
+ void (*device_init)(struct phb *phb, struct pci_device *device);
+
+ /*
+ * EEH methods
+ *
+ * The various arguments are identical to the corresponding
+ * OPAL functions
+ */
+ int64_t (*eeh_freeze_status)(struct phb *phb, uint64_t pe_number,
+ uint8_t *freeze_state,
+ uint16_t *pci_error_type,
+ uint16_t *severity,
+ uint64_t *phb_status);
+ int64_t (*eeh_freeze_clear)(struct phb *phb, uint64_t pe_number,
+ uint64_t eeh_action_token);
+
+ int64_t (*get_diag_data)(struct phb *phb, void *diag_buffer,
+ uint64_t diag_buffer_len);
+ int64_t (*get_diag_data2)(struct phb *phb, void *diag_buffer,
+ uint64_t diag_buffer_len);
+ int64_t (*next_error)(struct phb *phb, uint64_t *first_frozen_pe,
+ uint16_t *pci_error_type, uint16_t *severity);
+
+ /*
+ * Other IODA methods
+ *
+ * The various arguments are identical to the corresponding
+ * OPAL functions
+ */
+ int64_t (*pci_reinit)(struct phb *phb, uint64_t scope, uint64_t data);
+ int64_t (*phb_mmio_enable)(struct phb *phb, uint16_t window_type,
+ uint16_t window_num, uint16_t enable);
+
+ int64_t (*set_phb_mem_window)(struct phb *phb, uint16_t window_type,
+ uint16_t window_num, uint64_t addr,
+ uint64_t pci_addr, uint64_t size);
+
+ int64_t (*map_pe_mmio_window)(struct phb *phb, uint16_t pe_number,
+ uint16_t window_type, uint16_t window_num,
+ uint16_t segment_num);
+
+ int64_t (*set_pe)(struct phb *phb, uint64_t pe_number,
+ uint64_t bus_dev_func, uint8_t bus_compare,
+ uint8_t dev_compare, uint8_t func_compare,
+ uint8_t pe_action);
+
+ int64_t (*set_peltv)(struct phb *phb, uint32_t parent_pe,
+ uint32_t child_pe, uint8_t state);
+
+ int64_t (*map_pe_dma_window)(struct phb *phb, uint16_t pe_number,
+ uint16_t window_id, uint16_t tce_levels,
+ uint64_t tce_table_addr,
+ uint64_t tce_table_size,
+ uint64_t tce_page_size);
+
+ int64_t (*map_pe_dma_window_real)(struct phb *phb, uint16_t pe_number,
+ uint16_t dma_window_number,
+ uint64_t pci_start_addr,
+ uint64_t pci_mem_size);
+
+ int64_t (*set_mve)(struct phb *phb, uint32_t mve_number,
+ uint32_t pe_number);
+
+ int64_t (*set_mve_enable)(struct phb *phb, uint32_t mve_number,
+ uint32_t state);
+
+ int64_t (*set_xive_pe)(struct phb *phb, uint32_t pe_number,
+ uint32_t xive_num);
+
+ int64_t (*get_xive_source)(struct phb *phb, uint32_t xive_num,
+ int32_t *interrupt_source_number);
+
+ int64_t (*get_msi_32)(struct phb *phb, uint32_t mve_number,
+ uint32_t xive_num, uint8_t msi_range,
+ uint32_t *msi_address, uint32_t *message_data);
+
+ int64_t (*get_msi_64)(struct phb *phb, uint32_t mve_number,
+ uint32_t xive_num, uint8_t msi_range,
+ uint64_t *msi_address, uint32_t *message_data);
+
+ int64_t (*ioda_reset)(struct phb *phb, bool purge);
+
+ /*
+ * P5IOC2 only
+ */
+ int64_t (*set_phb_tce_memory)(struct phb *phb, uint64_t tce_mem_addr,
+ uint64_t tce_mem_size);
+
+ /*
+ * IODA2 PCI interfaces
+ */
+ int64_t (*pci_msi_eoi)(struct phb *phb, uint32_t hwirq);
+
+ /*
+ * Slot control
+ */
+
+ /* presence_detect - Check for a present device
+ *
+ * Immediate return of:
+ *
+ * OPAL_SHPC_DEV_NOT_PRESENT = 0,
+ * OPAL_SHPC_DEV_PRESENT = 1
+ *
+ * or a negative OPAL error code
+ */
+ int64_t (*presence_detect)(struct phb *phb);
+
+ /* link_state - Check link state
+ *
+ * Immediate return of:
+ *
+ * OPAL_SHPC_LINK_DOWN = 0,
+ * OPAL_SHPC_LINK_UP_x1 = 1,
+ * OPAL_SHPC_LINK_UP_x2 = 2,
+ * OPAL_SHPC_LINK_UP_x4 = 4,
+ * OPAL_SHPC_LINK_UP_x8 = 8,
+ * OPAL_SHPC_LINK_UP_x16 = 16,
+ * OPAL_SHPC_LINK_UP_x32 = 32
+ *
+ * or a negative OPAL error code
+ */
+ int64_t (*link_state)(struct phb *phb);
+
+ /* power_state - Check slot power state
+ *
+ * Immediate return of:
+ *
+ * OPAL_SLOT_POWER_OFF = 0,
+ * OPAL_SLOT_POWER_ON = 1,
+ *
+ * or a negative OPAL error code
+ */
+ int64_t (*power_state)(struct phb *phb);
+
+ /* slot_power_off - Start slot power off sequence
+ *
+ * Asynchronous function, returns a positive delay
+ * or a negative error code
+ */
+ int64_t (*slot_power_off)(struct phb *phb);
+
+ /* slot_power_on - Start slot power on sequence
+ *
+ * Asynchronous function, returns a positive delay
+ * or a negative error code.
+ */
+ int64_t (*slot_power_on)(struct phb *phb);
+
+ /* PHB power off and on after complete init */
+ int64_t (*complete_reset)(struct phb *phb, uint8_t assert);
+
+ /* hot_reset - Hot Reset sequence */
+ int64_t (*hot_reset)(struct phb *phb);
+
+ /* Fundamental reset */
+ int64_t (*fundamental_reset)(struct phb *phb);
+
+ /* poll - Poll and advance asynchronous operations
+ *
+ * Returns a positive delay, 0 for success or a
+ * negative OPAL error code
+ */
+ int64_t (*poll)(struct phb *phb);
+
+ /* Put phb in capi mode or pcie mode */
+ int64_t (*set_capi_mode)(struct phb *phb, uint64_t mode, uint64_t pe_number);
+};
+
+enum phb_type {
+ phb_type_pci,
+ phb_type_pcix_v1,
+ phb_type_pcix_v2,
+ phb_type_pcie_v1,
+ phb_type_pcie_v2,
+ phb_type_pcie_v3,
+};
+
+struct phb {
+ struct dt_node *dt_node;
+ int opal_id;
+ uint32_t scan_map;
+ enum phb_type phb_type;
+ struct list_head devices;
+ const struct phb_ops *ops;
+ struct pci_lsi_state lstate;
+ uint32_t mps;
+
+ /* PCI-X only slot info, for PCI-E this is in the RC bridge */
+ struct pci_slot_info *slot_info;
+
+ /* Base location code used to generate the children one */
+ const char *base_loc_code;
+
+ /* Additional data the platform might need to attach */
+ void *platform_data;
+};
+
+/* Config space ops wrappers */
+static inline int64_t pci_cfg_read8(struct phb *phb, uint32_t bdfn,
+ uint32_t offset, uint8_t *data)
+{
+ return phb->ops->cfg_read8(phb, bdfn, offset, data);
+}
+
+static inline int64_t pci_cfg_read16(struct phb *phb, uint32_t bdfn,
+ uint32_t offset, uint16_t *data)
+{
+ return phb->ops->cfg_read16(phb, bdfn, offset, data);
+}
+
+static inline int64_t pci_cfg_read32(struct phb *phb, uint32_t bdfn,
+ uint32_t offset, uint32_t *data)
+{
+ return phb->ops->cfg_read32(phb, bdfn, offset, data);
+}
+
+static inline int64_t pci_cfg_write8(struct phb *phb, uint32_t bdfn,
+ uint32_t offset, uint8_t data)
+{
+ return phb->ops->cfg_write8(phb, bdfn, offset, data);
+}
+
+static inline int64_t pci_cfg_write16(struct phb *phb, uint32_t bdfn,
+ uint32_t offset, uint16_t data)
+{
+ return phb->ops->cfg_write16(phb, bdfn, offset, data);
+}
+
+static inline int64_t pci_cfg_write32(struct phb *phb, uint32_t bdfn,
+ uint32_t offset, uint32_t data)
+{
+ return phb->ops->cfg_write32(phb, bdfn, offset, data);
+}
+
+/* Utilities */
+extern int64_t pci_find_cap(struct phb *phb, uint16_t bdfn, uint8_t cap);
+extern int64_t pci_find_ecap(struct phb *phb, uint16_t bdfn, uint16_t cap,
+ uint8_t *version);
+extern int32_t pci_configure_mps(struct phb *phb, struct pci_device *pd);
+
+extern struct pci_device *pci_walk_dev(struct phb *phb,
+ int (*cb)(struct phb *,
+ struct pci_device *,
+ void *),
+ void *userdata);
+extern struct pci_device *pci_find_dev(struct phb *phb, uint16_t bdfn);
+
+/* Manage PHBs */
+extern int64_t pci_register_phb(struct phb *phb);
+extern int64_t pci_unregister_phb(struct phb *phb);
+extern struct phb *pci_get_phb(uint64_t phb_id);
+static inline void pci_put_phb(struct phb *phb __unused) { }
+
+/* Device tree */
+extern void pci_std_swizzle_irq_map(struct dt_node *dt_node,
+ struct pci_device *pd,
+ struct pci_lsi_state *lstate,
+ uint8_t swizzle);
+
+/* Initialize all PCI slots */
+extern void pci_init_slots(void);
+extern void pci_reset(void);
+
+#endif /* __PCI_H */
diff --git a/include/phb3-regs.h b/include/phb3-regs.h
new file mode 100644
index 0000000..0aaab9a
--- /dev/null
+++ b/include/phb3-regs.h
@@ -0,0 +1,436 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PHB3_REGS_H
+#define __PHB3_REGS_H
+
+
+/*
+ * PHB registers
+ */
+
+/* PHB Fundamental register set A */
+#define PHB_LSI_SOURCE_ID 0x100
+#define PHB_LSI_SRC_ID_MASK PPC_BITMASK(5,12)
+#define PHB_LSI_SRC_ID_LSH PPC_BITLSHIFT(12)
+#define PHB_DMA_CHAN_STATUS 0x110
+#define PHB_DMA_CHAN_ANY_ERR PPC_BIT(27)
+#define PHB_DMA_CHAN_ANY_ERR1 PPC_BIT(28)
+#define PHB_DMA_CHAN_ANY_FREEZE PPC_BIT(29)
+#define PHB_CPU_LOADSTORE_STATUS 0x120
+#define PHB_CPU_LS_ANY_ERR PPC_BIT(27)
+#define PHB_CPU_LS_ANY_ERR1 PPC_BIT(28)
+#define PHB_CPU_LS_ANY_FREEZE PPC_BIT(29)
+#define PHB_DMA_MSI_NODE_ID 0x128
+#define PHB_DMAMSI_NID_FIXED PPC_BIT(0)
+#define PHB_DMAMSI_NID_MASK PPC_BITMASK(24,31)
+#define PHB_DMAMSI_NID_LSH PPC_BITLSHIFT(31)
+#define PHB_CONFIG_DATA 0x130
+#define PHB_LOCK0 0x138
+#define PHB_CONFIG_ADDRESS 0x140
+#define PHB_CA_ENABLE PPC_BIT(0)
+#define PHB_CA_BUS_MASK PPC_BITMASK(4,11)
+#define PHB_CA_BUS_LSH PPC_BITLSHIFT(11)
+#define PHB_CA_DEV_MASK PPC_BITMASK(12,16)
+#define PHB_CA_DEV_LSH PPC_BITLSHIFT(16)
+#define PHB_CA_FUNC_MASK PPC_BITMASK(17,19)
+#define PHB_CA_FUNC_LSH PPC_BITLSHIFT(19)
+#define PHB_CA_REG_MASK PPC_BITMASK(20,31)
+#define PHB_CA_REG_LSH PPC_BITLSHIFT(31)
+#define PHB_CA_PE_MASK PPC_BITMASK(40,47)
+#define PHB_CA_PE_LSH PPC_BITLSHIFT(47)
+#define PHB_LOCK1 0x148
+#define PHB_IVT_BAR 0x150
+#define PHB_IVT_BAR_ENABLE PPC_BIT(0)
+#define PHB_IVT_BASE_ADDRESS_MASK PPC_BITMASK(14,48)
+#define PHB_IVT_BASE_ADDRESS_LSH PPC_BITLSHIFT(48)
+#define PHB_IVT_LENGTH_MASK PPC_BITMASK(52,63)
+#define PHB_IVT_LENGTH_ADDRESS_LSH PPC_BITLSHIFT(63)
+#define PHB_RBA_BAR 0x158
+#define PHB_RBA_BAR_ENABLE PPC_BIT(0)
+#define PHB_RBA_BASE_ADDRESS_MASK PPC_BITMASK(14,55)
+#define PHB_RBA_BASE_ADDRESS_LSH PPC_BITLSHIFT(55)
+#define PHB_PHB3_CONFIG 0x160
+#define PHB_PHB3C_64B_TCE_EN PPC_BIT(2)
+#define PHB_PHB3C_32BIT_MSI_EN PPC_BIT(8)
+#define PHB_PHB3C_64BIT_MSI_EN PPC_BIT(14)
+#define PHB_PHB3C_M32_EN PPC_BIT(16)
+#define PHB_RTT_BAR 0x168
+#define PHB_RTT_BAR_ENABLE PPC_BIT(0)
+#define PHB_RTT_BASE_ADDRESS_MASK PPC_BITMASK(14,46)
+#define PHB_RTT_BASE_ADDRESS_LSH PPC_BITLSHIFT(46)
+#define PHB_PELTV_BAR 0x188
+#define PHB_PELTV_BAR_ENABLE PPC_BIT(0)
+#define PHB_PELTV_BASE_ADDRESS_MASK PPC_BITMASK(14,50)
+#define PHB_PELTV_BASE_ADDRESS_LSH PPC_BITLSHIFT(50)
+#define PHB_M32_BASE_ADDR 0x190
+#define PHB_M32_BASE_MASK 0x198
+#define PHB_M32_START_ADDR 0x1a0
+#define PHB_PEST_BAR 0x1a8
+#define PHB_PEST_BAR_ENABLE PPC_BIT(0)
+#define PHB_PEST_BASE_ADDRESS_MASK PPC_BITMASK(14,51)
+#define PHB_PEST_BASE_ADDRESS_LSH PPC_BITLSHIFT(51)
+#define PHB_M64_UPPER_BITS 0x1f0
+#define PHB_INTREP_TIMER 0x1f8
+#define PHB_DMARD_SYNC 0x200
+#define PHB_RTC_INVALIDATE 0x208
+#define PHB_RTC_INVALIDATE_ALL PPC_BIT(0)
+#define PHB_RTC_INVALIDATE_RID_MASK PPC_BITMASK(16,31)
+#define PHB_RTC_INVALIDATE_RID_LSH PPC_BITLSHIFT(31)
+#define PHB_TCE_KILL 0x210
+#define PHB_TCE_KILL_ALL PPC_BIT(0)
+#define PHB_TCE_SPEC_CTL 0x218
+#define PHB_IODA_ADDR 0x220
+#define PHB_IODA_AD_AUTOINC PPC_BIT(0)
+#define PHB_IODA_AD_TSEL_MASK PPC_BITMASK(11,15)
+#define PHB_IODA_AD_TSEL_LSH PPC_BITLSHIFT(15)
+#define PHB_IODA_AD_TADR_MASK PPC_BITMASK(55,63)
+#define PHB_IODA_AD_TADR_LSH PPC_BITLSHIFT(63)
+#define PHB_IODA_DATA0 0x228
+#define PHB_FFI_REQUEST 0x238
+#define PHB_FFI_LOCK_CLEAR PPC_BIT(3)
+#define PHB_FFI_REQUEST_ISN_MASK PPC_BITMASK(49,59)
+#define PHB_FFI_REQUEST_ISN_LSH PPC_BITLSHIFT(59)
+#define PHB_FFI_LOCK 0x240
+#define PHB_XIVE_UPDATE 0x248 /* Broken in DD1 */
+#define PHB_PHB3_GEN_CAP 0x250
+#define PHB_PHB3_TCE_CAP 0x258
+#define PHB_PHB3_IRQ_CAP 0x260
+#define PHB_PHB3_EEH_CAP 0x268
+#define PHB_IVC_INVALIDATE 0x2a0
+#define PHB_IVC_INVALIDATE_ALL PPC_BIT(0)
+#define PHB_IVC_INVALIDATE_SID_MASK PPC_BITMASK(16,31)
+#define PHB_IVC_INVALIDATE_SID_LSH PPC_BITLSHIFT(31)
+#define PHB_IVC_UPDATE 0x2a8
+#define PHB_IVC_UPDATE_ENABLE_P PPC_BIT(0)
+#define PHB_IVC_UPDATE_ENABLE_Q PPC_BIT(1)
+#define PHB_IVC_UPDATE_ENABLE_SERVER PPC_BIT(2)
+#define PHB_IVC_UPDATE_ENABLE_PRI PPC_BIT(3)
+#define PHB_IVC_UPDATE_ENABLE_GEN PPC_BIT(4)
+#define PHB_IVC_UPDATE_ENABLE_CON PPC_BIT(5)
+#define PHB_IVC_UPDATE_GEN_MATCH_MASK PPC_BITMASK(6, 7)
+#define PHB_IVC_UPDATE_GEN_MATCH_LSH PPC_BITLSHIFT(7)
+#define PHB_IVC_UPDATE_SERVER_MASK PPC_BITMASK(8, 23)
+#define PHB_IVC_UPDATE_SERVER_LSH PPC_BITLSHIFT(23)
+#define PHB_IVC_UPDATE_PRI_MASK PPC_BITMASK(24, 31)
+#define PHB_IVC_UPDATE_PRI_LSH PPC_BITLSHIFT(31)
+#define PHB_IVC_UPDATE_GEN_MASK PPC_BITMASK(32,33)
+#define PHB_IVC_UPDATE_GEN_LSH PPC_BITLSHIFT(33)
+#define PHB_IVC_UPDATE_P_MASK PPC_BITMASK(34,34)
+#define PHB_IVC_UPDATE_P_LSH PPC_BITLSHIFT(34)
+#define PHB_IVC_UPDATE_Q_MASK PPC_BITMASK(35,35)
+#define PHB_IVC_UPDATE_Q_LSH PPC_BITLSHIFT(35)
+#define PHB_IVC_UPDATE_SID_MASK PPC_BITMASK(48,63)
+#define PHB_IVC_UPDATE_SID_LSH PPC_BITLSHIFT(63)
+#define PHB_PAPR_ERR_INJ_CONTROL 0x2b0
+#define PHB_PAPR_ERR_INJ_ADDR 0x2b8
+#define PHB_PAPR_ERR_INJ_MASK 0x2c0
+#define PHB_ETU_ERR_SUMMARY 0x2c8
+
+/* UTL registers */
+#define UTL_SYS_BUS_CONTROL 0x400
+#define UTL_STATUS 0x408
+#define UTL_SYS_BUS_AGENT_STATUS 0x410
+#define UTL_SYS_BUS_AGENT_ERR_SEVERITY 0x418
+#define UTL_SYS_BUS_AGENT_IRQ_EN 0x420
+#define UTL_SYS_BUS_BURST_SZ_CONF 0x440
+#define UTL_REVISION_ID 0x448
+#define UTL_BCLK_DOMAIN_DBG1 0x460
+#define UTL_BCLK_DOMAIN_DBG2 0x468
+#define UTL_BCLK_DOMAIN_DBG3 0x470
+#define UTL_BCLK_DOMAIN_DBG4 0x478
+#define UTL_BCLK_DOMAIN_DBG5 0x480
+#define UTL_BCLK_DOMAIN_DBG6 0x488
+#define UTL_OUT_POST_HDR_BUF_ALLOC 0x4c0
+#define UTL_OUT_POST_DAT_BUF_ALLOC 0x4d0
+#define UTL_IN_POST_HDR_BUF_ALLOC 0x4e0
+#define UTL_IN_POST_DAT_BUF_ALLOC 0x4f0
+#define UTL_OUT_NP_BUF_ALLOC 0x500
+#define UTL_IN_NP_BUF_ALLOC 0x510
+#define UTL_PCIE_TAGS_ALLOC 0x520
+#define UTL_GBIF_READ_TAGS_ALLOC 0x530
+#define UTL_PCIE_PORT_CONTROL 0x540
+#define UTL_PCIE_PORT_STATUS 0x548
+#define UTL_PCIE_PORT_ERROR_SEV 0x550
+#define UTL_PCIE_PORT_IRQ_EN 0x558
+#define UTL_RC_STATUS 0x560
+#define UTL_RC_ERR_SEVERITY 0x568
+#define UTL_RC_IRQ_EN 0x570
+#define UTL_EP_STATUS 0x578
+#define UTL_EP_ERR_SEVERITY 0x580
+#define UTL_EP_ERR_IRQ_EN 0x588
+#define UTL_PCI_PM_CTRL1 0x590
+#define UTL_PCI_PM_CTRL2 0x598
+#define UTL_GP_CTL1 0x5a0
+#define UTL_GP_CTL2 0x5a8
+#define UTL_PCLK_DOMAIN_DBG1 0x5b0
+#define UTL_PCLK_DOMAIN_DBG2 0x5b8
+#define UTL_PCLK_DOMAIN_DBG3 0x5c0
+#define UTL_PCLK_DOMAIN_DBG4 0x5c8
+
+/* PCI-E Stack registers */
+#define PHB_PCIE_SYSTEM_CONFIG 0x600
+#define PHB_PCIE_BUS_NUMBER 0x608
+#define PHB_PCIE_SYSTEM_TEST 0x618
+#define PHB_PCIE_LINK_MANAGEMENT 0x630
+#define PHB_PCIE_LM_LINK_ACTIVE PPC_BIT(8)
+#define PHB_PCIE_DLP_TRAIN_CTL 0x640
+#define PHB_PCIE_DLP_TCTX_DISABLE PPC_BIT(1)
+#define PHB_PCIE_DLP_TCRX_DISABLED PPC_BIT(16)
+#define PHB_PCIE_DLP_INBAND_PRESENCE PPC_BIT(19)
+#define PHB_PCIE_DLP_TC_DL_LINKUP PPC_BIT(21)
+#define PHB_PCIE_DLP_TC_DL_PGRESET PPC_BIT(22)
+#define PHB_PCIE_DLP_TC_DL_LINKACT PPC_BIT(23)
+#define PHB_PCIE_SLOP_LOOPBACK_STATUS 0x648
+#define PHB_PCIE_SYS_LINK_INIT 0x668
+#define PHB_PCIE_UTL_CONFIG 0x670
+#define PHB_PCIE_DLP_CONTROL 0x678
+#define PHB_PCIE_UTL_ERRLOG1 0x680
+#define PHB_PCIE_UTL_ERRLOG2 0x688
+#define PHB_PCIE_UTL_ERRLOG3 0x690
+#define PHB_PCIE_UTL_ERRLOG4 0x698
+#define PHB_PCIE_DLP_ERRLOG1 0x6a0
+#define PHB_PCIE_DLP_ERRLOG2 0x6a8
+#define PHB_PCIE_DLP_ERR_STATUS 0x6b0
+#define PHB_PCIE_DLP_ERR_COUNTERS 0x6b8
+#define PHB_PCIE_UTL_ERR_INJECT 0x6c0
+#define PHB_PCIE_TLDLP_ERR_INJECT 0x6c8
+#define PHB_PCIE_LANE_EQ_CNTL0 0x6d0
+#define PHB_PCIE_LANE_EQ_CNTL1 0x6d8
+#define PHB_PCIE_LANE_EQ_CNTL2 0x6e0
+#define PHB_PCIE_LANE_EQ_CNTL3 0x6e8
+#define PHB_PCIE_STRAPPING 0x700
+
+/* Fundamental register set B */
+#define PHB_VERSION 0x800
+#define PHB_RESET 0x808
+#define PHB_CONTROL 0x810
+#define PHB_AIB_RX_CRED_INIT_TIMER 0x818
+#define PHB_AIB_RX_CMD_CRED 0x820
+#define PHB_AIB_RX_DATA_CRED 0x828
+#define PHB_AIB_TX_CMD_CRED 0x830
+#define PHB_AIB_TX_DATA_CRED 0x838
+#define PHB_AIB_TX_CHAN_MAPPING 0x840
+#define PHB_AIB_TAG_ENABLE 0x858
+#define PHB_AIB_FENCE_CTRL 0x860
+#define PHB_TCE_TAG_ENABLE 0x868
+#define PHB_TCE_WATERMARK 0x870
+#define PHB_TIMEOUT_CTRL1 0x878
+#define PHB_TIMEOUT_CTRL2 0x880
+#define PHB_QUIESCE_DMA_G 0x888
+#define PHB_AIB_TAG_STATUS 0x900
+#define PHB_TCE_TAG_STATUS 0x908
+
+/* FIR & Error registers */
+#define PHB_LEM_FIR_ACCUM 0xc00
+#define PHB_LEM_FIR_AND_MASK 0xc08
+#define PHB_LEM_FIR_OR_MASK 0xc10
+#define PHB_LEM_ERROR_MASK 0xc18
+#define PHB_LEM_ERROR_AND_MASK 0xc20
+#define PHB_LEM_ERROR_OR_MASK 0xc28
+#define PHB_LEM_ACTION0 0xc30
+#define PHB_LEM_ACTION1 0xc38
+#define PHB_LEM_WOF 0xc40
+#define PHB_ERR_STATUS 0xc80
+#define PHB_ERR1_STATUS 0xc88
+#define PHB_ERR_INJECT 0xc90
+#define PHB_ERR_LEM_ENABLE 0xc98
+#define PHB_ERR_IRQ_ENABLE 0xca0
+#define PHB_ERR_FREEZE_ENABLE 0xca8
+#define PHB_ERR_AIB_FENCE_ENABLE 0xcb0
+#define PHB_ERR_LOG_0 0xcc0
+#define PHB_ERR_LOG_1 0xcc8
+#define PHB_ERR_STATUS_MASK 0xcd0
+#define PHB_ERR1_STATUS_MASK 0xcd8
+
+#define PHB_OUT_ERR_STATUS 0xd00
+#define PHB_OUT_ERR1_STATUS 0xd08
+#define PHB_OUT_ERR_INJECT 0xd10
+#define PHB_OUT_ERR_LEM_ENABLE 0xd18
+#define PHB_OUT_ERR_IRQ_ENABLE 0xd20
+#define PHB_OUT_ERR_FREEZE_ENABLE 0xd28
+#define PHB_OUT_ERR_AIB_FENCE_ENABLE 0xd30
+#define PHB_OUT_ERR_LOG_0 0xd40
+#define PHB_OUT_ERR_LOG_1 0xd48
+#define PHB_OUT_ERR_STATUS_MASK 0xd50
+#define PHB_OUT_ERR1_STATUS_MASK 0xd58
+
+#define PHB_INA_ERR_STATUS 0xd80
+#define PHB_INA_ERR1_STATUS 0xd88
+#define PHB_INA_ERR_INJECT 0xd90
+#define PHB_INA_ERR_LEM_ENABLE 0xd98
+#define PHB_INA_ERR_IRQ_ENABLE 0xda0
+#define PHB_INA_ERR_FREEZE_ENABLE 0xda8
+#define PHB_INA_ERR_AIB_FENCE_ENABLE 0xdb0
+#define PHB_INA_ERR_LOG_0 0xdc0
+#define PHB_INA_ERR_LOG_1 0xdc8
+#define PHB_INA_ERR_STATUS_MASK 0xdd0
+#define PHB_INA_ERR1_STATUS_MASK 0xdd8
+
+#define PHB_INB_ERR_STATUS 0xe00
+#define PHB_INB_ERR1_STATUS 0xe08
+#define PHB_INB_ERR_INJECT 0xe10
+#define PHB_INB_ERR_LEM_ENABLE 0xe18
+#define PHB_INB_ERR_IRQ_ENABLE 0xe20
+#define PHB_INB_ERR_FREEZE_ENABLE 0xe28
+#define PHB_INB_ERR_AIB_FENCE_ENABLE 0xe30
+#define PHB_INB_ERR_LOG_0 0xe40
+#define PHB_INB_ERR_LOG_1 0xe48
+#define PHB_INB_ERR_STATUS_MASK 0xe50
+#define PHB_INB_ERR1_STATUS_MASK 0xe58
+
+/* Performance monitor & Debug registers */
+#define PHB_TRACE_CONTROL 0xf80
+#define PHB_PERFMON_CONFIG 0xf88
+#define PHB_PERFMON_CTR0 0xf90
+#define PHB_PERFMON_CTR1 0xf98
+#define PHB_PERFMON_CTR2 0xfa0
+#define PHB_PERFMON_CTR3 0xfa8
+#define PHB_HOTPLUG_OVERRIDE 0xfb0
+#define PHB_HPOVR_FORCE_RESAMPLE PPC_BIT(9)
+#define PHB_HPOVR_PRESENCE_A PPC_BIT(10)
+#define PHB_HPOVR_PRESENCE_B PPC_BIT(11)
+#define PHB_HPOVR_LINK_ACTIVE PPC_BIT(12)
+#define PHB_HPOVR_LINK_BIFURCATED PPC_BIT(13)
+#define PHB_HPOVR_LINK_LANE_SWAPPED PPC_BIT(14)
+
+/*
+ * IODA2 on-chip tables
+ */
+
+#define IODA2_TBL_LIST 1
+#define IODA2_TBL_LXIVT 2
+#define IODA2_TBL_IVC_CAM 3
+#define IODA2_TBL_RBA 4
+#define IODA2_TBL_RCAM 5
+#define IODA2_TBL_MRT 6
+#define IODA2_TBL_PESTA 7
+#define IODA2_TBL_PESTB 8
+#define IODA2_TBL_TVT 9
+#define IODA2_TBL_TCAM 10
+#define IODA2_TBL_TDR 11
+#define IODA2_TBL_M64BT 16
+#define IODA2_TBL_M32DT 17
+#define IODA2_TBL_PEEV 20
+
+/* LXIVT */
+#define IODA2_LXIVT_SERVER_MASK PPC_BITMASK(8,23)
+#define IODA2_LXIVT_SERVER_LSH PPC_BITLSHIFT(23)
+#define IODA2_LXIVT_PRIORITY_MASK PPC_BITMASK(24,31)
+#define IODA2_LXIVT_PRIORITY_LSH PPC_BITLSHIFT(31)
+#define IODA2_LXIVT_NODE_ID_MASK PPC_BITMASK(56,63)
+#define IODA2_LXIVT_NODE_ID_LSH PPC_BITLSHIFT(63)
+
+/* IVT */
+#define IODA2_IVT_SERVER_MASK PPC_BITMASK(0,23)
+#define IODA2_IVT_SERVER_LSH PPC_BITLSHIFT(23)
+#define IODA2_IVT_PRIORITY_MASK PPC_BITMASK(24,31)
+#define IODA2_IVT_PRIORITY_LSH PPC_BITLSHIFT(31)
+#define IODA2_IVT_P_MASK PPC_BITMASK(39,39)
+#define IODA2_IVT_P_LSH PPC_BITLSHIFT(39)
+#define IODA2_IVT_Q_MASK PPC_BITMASK(47,47)
+#define IODA2_IVT_Q_LSH PPC_BITLSHIFT(47)
+#define IODA2_IVT_PE_MASK PPC_BITMASK(48,63)
+#define IODA2_IVT_PE_LSH PPC_BITLSHIFT(63)
+
+/* TVT */
+#define IODA2_TVT_TABLE_ADDR_MASK PPC_BITMASK(0,47)
+#define IODA2_TVT_TABLE_ADDR_LSH PPC_BITLSHIFT(47)
+#define IODA2_TVT_NUM_LEVELS_MASK PPC_BITMASK(48,50)
+#define IODA2_TVT_NUM_LEVELS_LSH PPC_BITLSHIFT(50)
+#define IODA2_TVE_1_LEVEL 0
+#define IODA2_TVE_2_LEVELS 1
+#define IODA2_TVE_3_LEVELS 2
+#define IODA2_TVE_4_LEVELS 3
+#define IODA2_TVE_5_LEVELS 4
+#define IODA2_TVT_TCE_TABLE_SIZE_MASK PPC_BITMASK(51,55)
+#define IODA2_TVT_TCE_TABLE_SIZE_LSH PPC_BITLSHIFT(55)
+#define IODA2_TVT_IO_PSIZE_MASK PPC_BITMASK(59,63)
+#define IODA2_TVT_IO_PSIZE_LSH PPC_BITLSHIFT(63)
+
+/* PESTA */
+#define IODA2_PESTA_MMIO_FROZEN PPC_BIT(0)
+
+/* PESTB */
+#define IODA2_PESTB_DMA_STOPPED PPC_BIT(0)
+
+/* M32DT */
+#define IODA2_M32DT_PE_MASK PPC_BITMASK(8,15)
+#define IODA2_M32DT_PE_LSH PPC_BITLSHIFT(15)
+
+/* M64BT */
+#define IODA2_M64BT_ENABLE PPC_BIT(0)
+#define IODA2_M64BT_SINGLE_PE PPC_BIT(1)
+#define IODA2_M64BT_BASE_MASK PPC_BITMASK(2,31)
+#define IODA2_M64BT_BASE_LSH PPC_BITLSHIFT(31)
+#define IODA2_M64BT_MASK_MASK PPC_BITMASK(34,63)
+#define IODA2_M64BT_MASK_LSH PPC_BITLSHIFT(63)
+#define IODA2_M64BT_SINGLE_BASE_MASK PPC_BITMASK(2,26)
+#define IODA2_M64BT_SINGLE_BASE_LSH PPC_BITLSHIFT(26)
+#define IODA2_M64BT_PE_HI_MASK PPC_BITMASK(27,31)
+#define IODA2_M64BT_PE_HI_LSH PPC_BITLSHIFT(31)
+#define IODA2_M64BT_SINGLE_MASK_MASK PPC_BITMASK(34,58)
+#define IODA2_M64BT_SINGLE_MASK_LSH PPC_BITLSHIFT(58)
+#define IODA2_M64BT_PE_LOW_MASK PPC_BITMASK(59,63)
+#define IODA2_M64BT_PE_LOW_LSH PPC_BITLSHIFT(63)
+
+/*
+ * IODA2 in-memory tables
+ */
+
+/* PEST
+ *
+ * 2x8 bytes entries, PEST0 and PEST1
+ */
+
+#define IODA2_PEST0_MMIO_CAUSE PPC_BIT(2)
+#define IODA2_PEST0_CFG_READ PPC_BIT(3)
+#define IODA2_PEST0_CFG_WRITE PPC_BIT(4)
+#define IODA2_PEST0_TTYPE_MASK PPC_BITMASK(5,7)
+#define IODA2_PEST0_TTYPE_LSH PPC_BITLSHIFT(7)
+#define PEST_TTYPE_DMA_WRITE 0
+#define PEST_TTYPE_MSI 1
+#define PEST_TTYPE_DMA_READ 2
+#define PEST_TTYPE_DMA_READ_RESP 3
+#define PEST_TTYPE_MMIO_LOAD 4
+#define PEST_TTYPE_MMIO_STORE 5
+#define PEST_TTYPE_OTHER 7
+#define IODA2_PEST0_CA_RETURN PPC_BIT(8)
+#define IODA2_PEST0_UTL_RTOS_TIMEOUT PPC_BIT(8) /* Same bit as CA return */
+#define IODA2_PEST0_UR_RETURN PPC_BIT(9)
+#define IODA2_PEST0_UTL_NONFATAL PPC_BIT(10)
+#define IODA2_PEST0_UTL_FATAL PPC_BIT(11)
+#define IODA2_PEST0_PARITY_UE PPC_BIT(13)
+#define IODA2_PEST0_UTL_CORRECTABLE PPC_BIT(14)
+#define IODA2_PEST0_UTL_INTERRUPT PPC_BIT(15)
+#define IODA2_PEST0_MMIO_XLATE PPC_BIT(16)
+#define IODA2_PEST0_IODA2_ERROR PPC_BIT(16) /* Same bit as MMIO xlate */
+#define IODA2_PEST0_TCE_PAGE_FAULT PPC_BIT(18)
+#define IODA2_PEST0_TCE_ACCESS_FAULT PPC_BIT(19)
+#define IODA2_PEST0_DMA_RESP_TIMEOUT PPC_BIT(20)
+#define IODA2_PEST0_AIB_SIZE_INVALID PPC_BIT(21)
+#define IODA2_PEST0_LEM_BIT_MASK PPC_BITMASK(26,31)
+#define IODA2_PEST0_LEM_BIT_LSH PPC_BITLSHIFT(31)
+#define IODA2_PEST0_RID_MASK PPC_BITMASK(32,47)
+#define IODA2_PEST0_RID_LSH PPC_BITLSHIFT(47)
+#define IODA2_PEST0_MSI_DATA_MASK PPC_BITMASK(48,63)
+#define IODA2_PEST0_MSI_DATA_LSH PPC_BITLSHIFT(63)
+
+#define IODA2_PEST1_FAIL_ADDR_MASK PPC_BITMASK(3,63)
+#define IODA2_PEST1_FAIL_ADDR_LSH PPC_BITLSHIFT(63)
+
+
+#endif /* __PHB3_REGS_H */
diff --git a/include/phb3.h b/include/phb3.h
new file mode 100644
index 0000000..9789336
--- /dev/null
+++ b/include/phb3.h
@@ -0,0 +1,355 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+*/
+#ifndef __PHB3_H
+#define __PHB3_H
+
+#include <interrupts.h>
+
+/*
+ * Memory map
+ *
+ * In addition to the 4K MMIO registers window, the PBCQ will
+ * forward down one or two large MMIO regions for use by the
+ * PHB.
+ *
+ * We try to use the largest MMIO window for the M64 space and
+ * the smallest for the M32 space, but we require at least 2G
+ * of M32, otherwise we carve it out of M64.
+ */
+
+#define M32_PCI_START 0x080000000 /* Offset of the actual M32 window in PCI */
+#define M32_PCI_SIZE 0x80000000ul /* Size for M32 */
+
+/*
+ * Interrupt map.
+ *
+ * Each PHB supports 2K interrupt sources, which is shared by
+ * LSI and MSI. With default configuration, MSI would use range
+ * [0, 0x7f7] and LSI would use [0x7f8, 0x7ff]. The interrupt
+ * source should be combined with IRSN to form final hardware
+ * IRQ.
+ */
+#define PHB3_MSI_IRQ_MIN 0x000
+#define PHB3_MSI_IRQ_COUNT 0x7F8
+#define PHB3_MSI_IRQ_MAX (PHB3_MSI_IRQ_MIN+PHB3_MSI_IRQ_COUNT-1)
+#define PHB3_LSI_IRQ_MIN (PHB3_MSI_IRQ_COUNT)
+#define PHB3_LSI_IRQ_COUNT 8
+#define PHB3_LSI_IRQ_MAX (PHB3_LSI_IRQ_MIN+PHB3_LSI_IRQ_COUNT-1)
+
+#define PHB3_MSI_IRQ_BASE(chip, phb) (P8_CHIP_IRQ_PHB_BASE(chip, phb) | \
+ PHB3_MSI_IRQ_MIN)
+#define PHB3_LSI_IRQ_BASE(chip, phb) (P8_CHIP_IRQ_PHB_BASE(chip, phb) | \
+ PHB3_LSI_IRQ_MIN)
+#define PHB3_IRQ_NUM(irq) (irq & 0x7FF)
+
+/*
+ * LSI interrupts
+ *
+ * The LSI interrupt block supports 8 interrupts. 4 of them are the
+ * standard PCIe INTA..INTB. The rest is for additional functions
+ * of the PHB
+ */
+#define PHB3_LSI_PCIE_INTA 0
+#define PHB3_LSI_PCIE_INTB 1
+#define PHB3_LSI_PCIE_INTC 2
+#define PHB3_LSI_PCIE_INTD 3
+#define PHB3_LSI_PCIE_INF 6
+#define PHB3_LSI_PCIE_ER 7
+
+/*
+ * In-memory tables
+ *
+ * PHB3 requires a bunch of tables to be in memory instead of
+ * arrays inside the chip (unlike previous versions of the
+ * design).
+ *
+ * Some of them (IVT, etc...) will be provided by the OS via an
+ * OPAL call, not only not all of them, we also need to make sure
+ * some like PELT-V exist before we do our internal slot probing
+ * or bad thing would happen on error (the whole PHB would go into
+ * Fatal error state).
+ *
+ * So we maintain a set of tables internally for those mandatory
+ * ones within our core memory. They are fairly small. They can
+ * still be replaced by OS provided ones via OPAL APIs (and reset
+ * to the internal ones) so the OS can provide node local allocation
+ * for better performances.
+ *
+ * All those tables have to be naturally aligned
+ */
+
+/* RTT Table : 128KB - Maps RID to PE#
+ *
+ * Entries are 2 bytes indexed by PCIe RID
+ */
+#define RTT_TABLE_ENTRIES 0x10000
+#define RTT_TABLE_SIZE (RTT_TABLE_ENTRIES * sizeof(struct rtt_entry))
+struct rtt_entry {
+ uint16_t pe_num;
+};
+
+/* IVT Table : MSI Interrupt vectors * state.
+ *
+ * We're sure that simics has 16-bytes IVE, totally 32KB.
+ * However the real HW possiblly has 128-bytes IVE, totally 256KB.
+ */
+#define IVT_TABLE_ENTRIES 0x800
+
+/* Default to 128-bytes IVEs, uncomment that to force it back to 16-bytes */
+//#define IVT_TABLE_IVE_16B
+
+#ifdef IVT_TABLE_IVE_16B
+#define IVT_TABLE_SIZE 0x8000
+#define IVT_TABLE_STRIDE 2 /* double-words */
+#else
+#define IVT_TABLE_SIZE 0x40000
+#define IVT_TABLE_STRIDE 16 /* double-words */
+#endif
+
+/* PELT-V Table : 8KB - Maps PE# to PE# dependencies
+ *
+ * 256 entries of 256 bits (32 bytes) each
+ */
+#define PELTV_TABLE_SIZE 0x2000
+
+/* PEST Table : 4KB - PE state table
+ *
+ * 256 entries of 16 bytes each containing state bits for each PE
+ *
+ * AFAIK: This acts as a backup for an on-chip cache and shall be
+ * accessed via the indirect IODA table access registers only
+ */
+#define PEST_TABLE_SIZE 0x1000
+
+/* RBA Table : 256 bytes - Reject Bit Array
+ *
+ * 2048 interrupts, 1 bit each, indiates the reject state of interrupts
+ */
+#define RBA_TABLE_SIZE 0x100
+
+/*
+ * Maximal supported PE# in PHB3. We probably probe it from EEH
+ * capability register later.
+ */
+#define PHB3_MAX_PE_NUM 256
+
+/*
+ * State structure for a PHB
+ */
+
+/*
+ * (Comment copied from p7ioc.h, please update both when relevant)
+ *
+ * The PHB State structure is essentially used during PHB reset
+ * or recovery operations to indicate that the PHB cannot currently
+ * be used for normal operations.
+ *
+ * Some states involve waiting for the timebase to reach a certain
+ * value. In which case the field "delay_tgt_tb" is set and the
+ * state machine will be run from the "state_poll" callback.
+ *
+ * At IPL time, we call this repeatedly during the various sequences
+ * however under OS control, this will require a change in API.
+ *
+ * Fortunately, the OPAL API for slot power & reset are not currently
+ * used by Linux, so changing them isn't going to be an issue. The idea
+ * here is that some of these APIs will return a positive integer when
+ * neededing such a delay to proceed. The OS will then be required to
+ * call a new function opal_poll_phb() after that delay. That function
+ * will potentially return a new delay, or OPAL_SUCCESS when the original
+ * operation has completed successfully. If the operation has completed
+ * with an error, then opal_poll_phb() will return that error.
+ *
+ * Note: Should we consider also returning optionally some indication
+ * of what operation is in progress for OS debug/diag purposes ?
+ *
+ * Any attempt at starting a new "asynchronous" operation while one is
+ * already in progress will result in an error.
+ *
+ * Internally, this is represented by the state being P7IOC_PHB_STATE_FUNCTIONAL
+ * when no operation is in progress, which it reaches at the end of the
+ * boot time initializations. Any attempt at performing a slot operation
+ * on a PHB in that state will change the state to the corresponding
+ * operation state machine. Any attempt while not in that state will
+ * return an error.
+ *
+ * Some operations allow for a certain amount of retries, this is
+ * provided for by the "retries" structure member for use by the state
+ * machine as it sees fit.
+ */
+enum phb3_state {
+ /* First init state */
+ PHB3_STATE_UNINITIALIZED,
+
+ /* During PHB HW inits */
+ PHB3_STATE_INITIALIZING,
+
+ /* Set if the PHB is for some reason unusable */
+ PHB3_STATE_BROKEN,
+
+ /* PHB fenced */
+ PHB3_STATE_FENCED,
+
+ /* Normal PHB functional state */
+ PHB3_STATE_FUNCTIONAL,
+
+ /* Hot reset */
+ PHB3_STATE_HRESET_DELAY,
+ PHB3_STATE_HRESET_DELAY2,
+
+ /* Fundamental reset */
+ PHB3_STATE_FRESET_ASSERT_DELAY,
+ PHB3_STATE_FRESET_DEASSERT_DELAY,
+
+ /* Complete reset */
+ PHB3_STATE_CRESET_WAIT_CQ,
+ PHB3_STATE_CRESET_REINIT,
+ PHB3_STATE_CRESET_FRESET,
+
+ /* Link state machine */
+ PHB3_STATE_WAIT_LINK_ELECTRICAL,
+ PHB3_STATE_WAIT_LINK,
+};
+
+/*
+ * PHB3 error descriptor. Errors from all components (PBCQ, PHB)
+ * will be cached to PHB3 instance. However, PBCQ errors would
+ * have higher priority than those from PHB
+ */
+#define PHB3_ERR_SRC_NONE 0
+#define PHB3_ERR_SRC_PBCQ 1
+#define PHB3_ERR_SRC_PHB 2
+
+#define PHB3_ERR_CLASS_NONE 0
+#define PHB3_ERR_CLASS_DEAD 1
+#define PHB3_ERR_CLASS_FENCED 2
+#define PHB3_ERR_CLASS_ER 3
+#define PHB3_ERR_CLASS_INF 4
+#define PHB3_ERR_CLASS_LAST 5
+
+struct phb3_err {
+ uint32_t err_src;
+ uint32_t err_class;
+ uint32_t err_bit;
+};
+
+/* Link timeouts, increments of 100ms */
+#define PHB3_LINK_WAIT_RETRIES 20
+#define PHB3_LINK_ELECTRICAL_RETRIES 10
+
+/* PHB3 flags */
+#define PHB3_AIB_FENCED 0x00000001
+#define PHB3_CFG_USE_ASB 0x00000002
+#define PHB3_CFG_BLOCKED 0x00000004
+
+struct phb3 {
+ unsigned int index; /* 0..2 index inside P8 */
+ unsigned int flags;
+ unsigned int chip_id; /* Chip ID (== GCID on P8) */
+ unsigned int rev; /* 00MMmmmm */
+#define PHB3_REV_MURANO_DD10 0xa30001
+#define PHB3_REV_VENICE_DD10 0xa30002
+#define PHB3_REV_MURANO_DD20 0xa30003
+#define PHB3_REV_MURANO_DD21 0xa30004
+#define PHB3_REV_VENICE_DD20 0xa30005
+ void *regs;
+ uint64_t pe_xscom; /* XSCOM bases */
+ uint64_t pci_xscom;
+ uint64_t spci_xscom;
+ struct lock lock;
+ uint64_t mm0_base; /* Full MM window to PHB */
+ uint64_t mm0_size; /* '' '' '' */
+ uint64_t mm1_base; /* Full MM window to PHB */
+ uint64_t mm1_size; /* '' '' '' */
+ uint32_t base_msi;
+ uint32_t base_lsi;
+
+ /* SkiBoot owned in-memory tables */
+ uint64_t tbl_rtt;
+ uint64_t tbl_peltv;
+ uint64_t tbl_pest;
+ uint64_t tbl_ivt;
+ uint64_t tbl_rba;
+
+ bool skip_perst; /* Skip first perst */
+ bool has_link;
+ bool use_ab_detect;
+ enum phb3_state state;
+ uint64_t delay_tgt_tb;
+ uint64_t retries;
+ int64_t ecap; /* cached PCI-E cap offset */
+ int64_t aercap; /* cached AER ecap offset */
+ const __be64 *lane_eq;
+ uint64_t capp_ucode_base;
+ bool capp_ucode_loaded;
+ unsigned int max_link_speed;
+
+ uint16_t rte_cache[RTT_TABLE_SIZE/2];
+ uint8_t peltv_cache[PELTV_TABLE_SIZE];
+ uint64_t lxive_cache[8];
+ uint64_t ive_cache[IVT_TABLE_ENTRIES];
+ uint64_t tve_cache[512];
+ uint64_t m32d_cache[256];
+ uint64_t m64b_cache[16];
+ uint64_t nfir_cache; /* Used by complete reset */
+ bool err_pending;
+ struct phb3_err err;
+
+ struct phb phb;
+};
+
+static inline struct phb3 *phb_to_phb3(struct phb *phb)
+{
+ return container_of(phb, struct phb3, phb);
+}
+
+static inline uint64_t phb3_read_reg_asb(struct phb3 *p, uint64_t offset)
+{
+ uint64_t val;
+
+ xscom_write(p->chip_id, p->spci_xscom, offset);
+ xscom_read(p->chip_id, p->spci_xscom + 0x2, &val);
+
+ return val;
+}
+
+static inline void phb3_write_reg_asb(struct phb3 *p,
+ uint64_t offset, uint64_t val)
+{
+ xscom_write(p->chip_id, p->spci_xscom, offset);
+ xscom_write(p->chip_id, p->spci_xscom + 0x2, val);
+}
+
+static inline bool phb3_err_pending(struct phb3 *p)
+{
+ return p->err_pending;
+}
+
+static inline void phb3_set_err_pending(struct phb3 *p, bool pending)
+{
+ if (!pending) {
+ p->err.err_src = PHB3_ERR_SRC_NONE;
+ p->err.err_class = PHB3_ERR_CLASS_NONE;
+ p->err.err_bit = -1;
+ }
+
+ p->err_pending = pending;
+}
+
+#endif /* __PHB3_H */
diff --git a/include/platform.h b/include/platform.h
new file mode 100644
index 0000000..689a80b
--- /dev/null
+++ b/include/platform.h
@@ -0,0 +1,122 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PLATFORM_H
+#define __PLATFORM_H
+
+/* Some fwd declarations for types used further down */
+struct phb;
+struct pci_device;
+
+/*
+ * Each platform can provide a set of hooks
+ * that can affect the generic code
+ */
+struct platform {
+ const char *name;
+
+ /*
+ * Probe platform, return true on a match, called before
+ * any allocation has been performed outside of the heap
+ * so the platform can perform additional memory reservations
+ * here if needed.
+ *
+ * Only the boot CPU is running at this point and the cpu_thread
+ * structure for secondaries have not been initialized yet. The
+ * timebases are not synchronized.
+ *
+ * Services available:
+ *
+ * - Memory allocations / reservations
+ * - XSCOM
+ * - FSI
+ * - Host Services
+ */
+ bool (*probe)(void);
+
+ /*
+ * This is called right after the secondary processors are brought
+ * up and the timebases in sync to perform any additional platform
+ * specific initializations. On FSP based machines, this is where
+ * the FSP driver is brought up.
+ */
+ void (*init)(void);
+
+ /*
+ * These are used to power down and reboot the machine
+ */
+ int64_t (*cec_power_down)(uint64_t request);
+ int64_t (*cec_reboot)(void);
+
+ /*
+ * This is called once per PHB before probing. It allows the
+ * platform to setup some PHB private data that can be used
+ * later on by calls such as pci_get_slot_info() below. The
+ * "index" argument is the PHB index within the IO HUB (or
+ * P8 chip).
+ *
+ * This is called before the PHB HW has been initialized.
+ */
+ void (*pci_setup_phb)(struct phb *phb, unsigned int index);
+
+ /*
+ * Called during PCI scan for each device. For bridges, this is
+ * called before its children are probed. This is called for
+ * every device and for the PHB itself with a NULL pd though
+ * typically the implementation will only populate the slot
+ * info structure for bridge ports
+ */
+ void (*pci_get_slot_info)(struct phb *phb,
+ struct pci_device *pd);
+
+ /*
+ * Called after PCI probe is complete and before inventory is
+ * displayed in console. This can either run platform fixups or
+ * can be used to send the inventory to a service processor.
+ */
+ void (*pci_probe_complete)(void);
+
+ /*
+ * If the above is set to skiboot, the handler is here
+ */
+ void (*external_irq)(unsigned int chip_id);
+
+ /*
+ * nvram ops.
+ *
+ * Note: To keep the FSP driver simple, we only ever read the
+ * whole nvram once at boot and we do this passing a dst buffer
+ * that is 4K aligned. The read is asynchronous, the backend
+ * must call nvram_read_complete() when done (it's allowed to
+ * do it recursively from nvram_read though).
+ */
+ int (*nvram_info)(uint32_t *total_size);
+ int (*nvram_start_read)(void *dst, uint32_t src,
+ uint32_t len);
+ int (*nvram_write)(uint32_t dst, void *src, uint32_t len);
+};
+
+extern struct platform __platforms_start;
+extern struct platform __platforms_end;
+
+struct platform platform;
+
+#define DECLARE_PLATFORM(name)\
+static const struct platform __used __section(".platforms") name ##_platform
+
+extern void probe_platform(void);
+
+#endif /* __PLATFORM_H */
diff --git a/include/processor.h b/include/processor.h
new file mode 100644
index 0000000..c15e17e
--- /dev/null
+++ b/include/processor.h
@@ -0,0 +1,318 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PROCESSOR_H
+#define __PROCESSOR_H
+
+#include <bitutils.h>
+
+/* P7 MSR bits */
+#define MSR_SF PPC_BIT(0) /* 64-bit mode */
+#define MSR_HV PPC_BIT(3) /* Hypervisor mode */
+#define MSR_VEC PPC_BIT(38) /* VMX enable */
+#define MSR_VSX PPC_BIT(40) /* VSX enable */
+#define MSR_EE PPC_BIT(48) /* External Int. Enable */
+#define MSR_PR PPC_BIT(49) /* Problem state */
+#define MSR_FP PPC_BIT(50) /* Floating Point Enable */
+#define MSR_ME PPC_BIT(51) /* Machine Check Enable */
+#define MSR_FE0 PPC_BIT(52) /* FP Exception 0 */
+#define MSR_SE PPC_BIT(53) /* Step enable */
+#define MSR_BE PPC_BIT(54) /* Branch trace enable */
+#define MSR_FE1 PPC_BIT(55) /* FP Exception 1 */
+#define MSR_IR PPC_BIT(58) /* Instructions reloc */
+#define MSR_DR PPC_BIT(59) /* Data reloc */
+#define MSR_PMM PPC_BIT(61) /* Perf Monitor */
+#define MSR_RI PPC_BIT(62) /* Recoverable Interrupt */
+#define MSR_LE PPC_BIT(63) /* Little Endian */
+
+/* PIR */
+#define SPR_PIR_P8_THREAD_MASK 0x0007 /* Mask of thread bits */
+#define SPR_PIR_P8_MASK 0x1fff /* Mask of implemented bits */
+#define SPR_PIR_P7_THREAD_MASK 0x0003 /* Mask of thread bits */
+#define SPR_PIR_P7_MASK 0x03ff /* Mask of implemented bits */
+
+/* SPR register definitions */
+#define SPR_DSISR 0x012 /* RW: Data storage interrupt status reg */
+#define SPR_DAR 0x013 /* RW: Data address reg */
+#define SPR_SDR1 0x019
+#define SPR_SRR0 0x01a /* RW: Exception save/restore reg 0 */
+#define SPR_SRR1 0x01b /* RW: Exception save/restore reg 1 */
+#define SPR_CFAR 0x01c /* RW: Come From Address Register */
+#define SPR_TBRL 0x10c /* RO: Timebase low */
+#define SPR_TBRU 0x10d /* RO: Timebase high */
+#define SPR_SPRC 0x114 /* RW: Access to uArch SPRs (ex SCOMC) */
+#define SPR_SPRD 0x115 /* RW: Access to uArch SPRs (ex SCOMD) */
+#define SPR_SCOMC 0x114 /* RW: SCOM Control - old name of SPRC */
+#define SPR_SCOMD 0x115 /* RW: SCOM Data - old name of SPRD */
+#define SPR_TBWL 0x11c /* RW: Timebase low */
+#define SPR_TBWU 0x11d /* RW: Timebase high */
+#define SPR_TBU40 0x11e /* RW: Timebase Upper 40 bit */
+#define SPR_PVR 0x11f /* RO: Processor version register */
+#define SPR_HSPRG0 0x130 /* RW: Hypervisor scratch 0 */
+#define SPR_HSPRG1 0x131 /* RW: Hypervisor scratch 1 */
+#define SPR_HSRR0 0x13a /* RW: HV Exception save/restore reg 0 */
+#define SPR_HSRR1 0x13b /* RW: HV Exception save/restore reg 1 */
+#define SPR_TFMR 0x13d
+#define SPR_LPCR 0x13e
+#define SPR_HMER 0x150 /* Hypervisor Maintenance Exception */
+#define SPR_HMEER 0x151 /* HMER interrupt enable mask */
+#define SPR_AMOR 0x15d
+#define SPR_TSCR 0x399
+#define SPR_HID0 0x3f0
+#define SPR_HID1 0x3f1
+#define SPR_HID2 0x3f8
+#define SPR_HID4 0x3f4
+#define SPR_HID5 0x3f6
+#define SPR_PIR 0x3ff /* RO: Processor Identification */
+
+/* Bits in LPCR */
+
+/* Powersave Exit Cause Enable is different for P7 and P8 */
+#define SPR_LPCR_P7_PECE PPC_BITMASK(49,51)
+#define SPR_LPCR_P7_PECE0 PPC_BIT(49) /* Wake on external interrupts */
+#define SPR_LPCR_P7_PECE1 PPC_BIT(50) /* Wake on decrementer */
+#define SPR_LPCR_P7_PECE2 PPC_BIT(51) /* Wake on MCs, HMIs, etc... */
+
+#define SPR_LPCR_P8_PECE PPC_BITMASK(47,51)
+#define SPR_LPCR_P8_PECE0 PPC_BIT(47) /* Wake on priv doorbell */
+#define SPR_LPCR_P8_PECE1 PPC_BIT(48) /* Wake on hv doorbell */
+#define SPR_LPCR_P8_PECE2 PPC_BIT(49) /* Wake on external interrupts */
+#define SPR_LPCR_P8_PECE3 PPC_BIT(50) /* Wake on decrementer */
+#define SPR_LPCR_P8_PECE4 PPC_BIT(51) /* Wake on MCs, HMIs, etc... */
+
+
+/* Bits in TFMR - control bits */
+#define SPR_TFMR_MAX_CYC_BET_STEPS_MASK PPC_BITMASK(0,7)
+#define SPR_TFMR_MAX_CYC_BET_STEPS_LSH PPC_BITLSHIFT(7)
+#define SPR_TFMR_N_CLKS_PER_STEP_MASK PPC_BITMASK(8,9)
+#define SPR_TFMR_N_CLKS_PER_STEP_LSH PPC_BITLSHIFT(9)
+#define SPR_TFMR_MASK_HMI PPC_BIT(10)
+#define SPR_TFMR_SYNC_BIT_SEL_MASK PPC_BITMASK(11,13)
+#define SPR_TFMR_SYNC_BIT_SEL_LSH PPC_BITLSHIFT(13)
+#define SPR_TFMR_TB_ECLIPZ PPC_BIT(14)
+#define SPR_TFMR_LOAD_TOD_MOD PPC_BIT(16)
+#define SPR_TFMR_MOVE_CHIP_TOD_TO_TB PPC_BIT(18)
+#define SPR_TFMR_CLEAR_TB_ERRORS PPC_BIT(24)
+/* Bits in TFMR - thread indep. status bits */
+#define SPR_TFMR_HDEC_PARITY_ERROR PPC_BIT(26)
+#define SPR_TFMR_TBST_CORRUPT PPC_BIT(27)
+#define SPR_TFMR_TBST_ENCODED_MASK PPC_BITMASK(28,31)
+#define SPR_TFMR_TBST_ENCODED_LSH PPC_BITLSHIFT(31)
+#define SPR_TFMR_TBST_LAST_MASK PPC_BITMASK(32,35)
+#define SPR_TFMR_TBST_LAST_LSH PPC_BITLSHIFT(35)
+#define SPR_TFMR_TB_ENABLED PPC_BIT(40)
+#define SPR_TFMR_TB_VALID PPC_BIT(41)
+#define SPR_TFMR_TB_SYNC_OCCURED PPC_BIT(42)
+#define SPR_TFMR_TB_MISSING_SYNC PPC_BIT(43)
+#define SPR_TFMR_TB_MISSING_STEP PPC_BIT(44)
+#define SPR_TFMR_TB_RESIDUE_ERR PPC_BIT(45)
+#define SPR_TFMR_FW_CONTROL_ERR PPC_BIT(46)
+#define SPR_TFMR_CHIP_TOD_STATUS_MASK PPC_BITMASK(47,50)
+#define SPR_TFMR_CHIP_TOD_STATUS_LSH PPC_BITLSHIFT(50)
+#define SPR_TFMR_CHIP_TOD_INTERRUPT PPC_BIT(51)
+#define SPR_TFMR_CHIP_TOD_TIMEOUT PPC_BIT(54)
+#define SPR_TFMR_CHIP_TOD_PARITY_ERR PPC_BIT(56)
+/* Bits in TFMR - thread specific. status bits */
+#define SPR_TFMR_PURR_PARITY_ERR PPC_BIT(57)
+#define SPR_TFMR_SPURR_PARITY_ERR PPC_BIT(58)
+#define SPR_TFMR_DEC_PARITY_ERR PPC_BIT(59)
+#define SPR_TFMR_TFMR_CORRUPT PPC_BIT(60)
+#define SPR_TFMR_PURR_OVERFLOW PPC_BIT(61)
+#define SPR_TFMR_SPURR_OVERFLOW PPC_BIT(62)
+
+/* Bits in HMER/HMEER */
+#define SPR_HMER_MALFUNCTION_ALERT PPC_BIT(0)
+#define SPR_HMER_PROC_RECV_DONE PPC_BIT(2)
+#define SPR_HMER_PROC_RECV_ERROR_MASKED PPC_BIT(3)
+#define SPR_HMER_TFAC_ERROR PPC_BIT(4)
+#define SPR_HMER_TFMR_PARITY_ERROR PPC_BIT(5)
+#define SPR_HMER_XSCOM_FAIL PPC_BIT(8)
+#define SPR_HMER_XSCOM_DONE PPC_BIT(9)
+#define SPR_HMER_PROC_RECV_AGAIN PPC_BIT(11)
+#define SPR_HMER_WARN_RISE PPC_BIT(14)
+#define SPR_HMER_WARN_FALL PPC_BIT(15)
+#define SPR_HMER_SCOM_FIR_HMI PPC_BIT(16)
+#define SPR_HMER_TRIG_FIR_HMI PPC_BIT(17)
+#define SPR_HMER_HYP_RESOURCE_ERR PPC_BIT(20)
+#define SPR_HMER_XSCOM_STATUS_MASK PPC_BITMASK(21,23)
+#define SPR_HMER_XSCOM_STATUS_LSH PPC_BITLSHIFT(23)
+
+/*
+ * HMEER: initial bits for HMI interrupt enable mask.
+ * Per Dave Larson, never enable 8,9,21-23
+ */
+#define SPR_HMEER_HMI_ENABLE_MASK (SPR_HMER_MALFUNCTION_ALERT |\
+ SPR_HMER_HYP_RESOURCE_ERR |\
+ SPR_HMER_PROC_RECV_DONE |\
+ SPR_HMER_PROC_RECV_ERROR_MASKED |\
+ SPR_HMER_TFAC_ERROR |\
+ SPR_HMER_TFMR_PARITY_ERROR |\
+ SPR_HMER_PROC_RECV_AGAIN)
+
+/* Bits in HID0 */
+#define SPR_HID0_HILE PPC_BIT(19)
+#define SPR_HID0_ENABLE_ATTN PPC_BIT(31)
+
+/* PVR bits */
+#define SPR_PVR_TYPE_MASK 0xffff0000
+#define SPR_PVR_TYPE_LSH 16
+#define SPR_PVR_VERS_MAJ_MASK 0x00000f00
+#define SPR_PVR_VERS_MAJ_LSH 8
+#define SPR_PVR_VERS_MIN_MASK 0x000000ff
+#define SPR_PVR_VERS_MIN_LSH 0
+
+#define PVR_TYPE(_pvr) GETFIELD(SPR_PVR_TYPE, _pvr)
+#define PVR_VERS_MAJ(_pvr) GETFIELD(SPR_PVR_VERS_MAJ, _pvr)
+#define PVR_VERS_MIN(_pvr) GETFIELD(SPR_PVR_VERS_MIN, _pvr)
+
+/* PVR definitions */
+#define PVR_TYPE_P7 0x003f
+#define PVR_TYPE_P7P 0x004a
+#define PVR_TYPE_P8E 0x004b /* Murano */
+#define PVR_TYPE_P8 0x004d /* Venice */
+
+#ifdef __ASSEMBLY__
+
+/* Thread priority control opcodes */
+#define smt_low or 1,1,1
+#define smt_medium or 2,2,2
+#define smt_high or 3,3,3
+#define smt_medium_high or 5,5,5
+#define smt_medium_low or 6,6,6
+#define smt_extra_high or 7,7,7
+#define smt_very_low or 31,31,31
+
+#else /* __ASSEMBLY__ */
+
+#include <compiler.h>
+#include <stdint.h>
+
+/*
+ * SMT priority
+ */
+
+static inline void smt_low(void) { asm volatile("or 1,1,1"); }
+static inline void smt_medium(void) { asm volatile("or 2,2,2"); }
+static inline void smt_high(void) { asm volatile("or 3,3,3"); }
+static inline void smt_medium_high(void){ asm volatile("or 5,5,5"); }
+static inline void smt_medium_low(void) { asm volatile("or 6,6,6"); }
+static inline void smt_extra_high(void) { asm volatile("or 7,7,7"); }
+static inline void smt_very_low(void) { asm volatile("or 31,31,31"); }
+
+/*
+ * SPR access functions
+ */
+
+static inline unsigned long mfmsr(void)
+{
+ unsigned long val;
+
+ asm volatile("mfmsr %0" : "=r"(val) : : "memory");
+ return val;
+}
+
+static inline void mtmsr(unsigned long val)
+{
+ asm volatile("mtmsr %0" : : "r"(val) : "memory");
+}
+
+static inline void mtmsrd(unsigned long val, int l)
+{
+ asm volatile("mtmsrd %0,%1" : : "r"(val), "i"(l) : "memory");
+}
+
+static inline unsigned long mfspr(unsigned int spr)
+{
+ unsigned long val;
+
+ asm volatile("mfspr %0,%1" : "=r"(val) : "i"(spr) : "memory");
+ return val;
+}
+
+static inline void mtspr(unsigned int spr, unsigned long val)
+{
+ asm volatile("mtspr %0,%1" : : "i"(spr), "r"(val) : "memory");
+}
+
+/* Helpers for special sequences needed by some registers */
+extern void set_hid0(unsigned long hid0);
+extern void trigger_attn(void);
+
+/*
+ * Barriers
+ */
+
+static inline void eieio(void)
+{
+ asm volatile("eieio" : : : "memory");
+}
+
+static inline void sync(void)
+{
+ asm volatile("sync" : : : "memory");
+}
+
+static inline void lwsync(void)
+{
+ asm volatile("lwsync" : : : "memory");
+}
+
+static inline void isync(void)
+{
+ asm volatile("isync" : : : "memory");
+}
+
+
+/*
+ * Cache sync
+ */
+static inline void sync_icache(void)
+{
+ asm volatile("sync; icbi 0,%0; sync; isync" : : "r" (0) : "memory");
+}
+
+
+/*
+ * Byteswap load/stores
+ */
+
+static inline uint16_t ld_le16(const uint16_t *addr)
+{
+ uint16_t val;
+ asm volatile("lhbrx %0,0,%1" : "=r"(val) : "r"(addr), "m"(*addr));
+ return val;
+}
+
+static inline uint32_t ld_le32(const uint32_t *addr)
+{
+ uint32_t val;
+ asm volatile("lwbrx %0,0,%1" : "=r"(val) : "r"(addr), "m"(*addr));
+ return val;
+}
+
+static inline void st_le16(uint16_t *addr, uint16_t val)
+{
+ asm volatile("sthbrx %0,0,%1" : : "r"(val), "r"(addr), "m"(*addr));
+}
+
+static inline void st_le32(uint32_t *addr, uint32_t val)
+{
+ asm volatile("stwbrx %0,0,%1" : : "r"(val), "r"(addr), "m"(*addr));
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __PROCESSOR_H */
diff --git a/include/psi.h b/include/psi.h
new file mode 100644
index 0000000..62232dc
--- /dev/null
+++ b/include/psi.h
@@ -0,0 +1,239 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/*
+ * IBM System P PSI (Processor Service Interface)
+ */
+#ifndef __PSI_H
+#define __PSI_H
+
+#include <skiboot.h>
+
+/*
+ * PSI Host Bridge Registers (MMIO)
+ *
+ * The PSI interface is the bridge to the FPS, it has its own
+ * registers. The FSP registers appear at an offset within the
+ * aperture defined by the PSI_FSPBAR
+ */
+/* Base address of the PSI MMIO space and LSB is the enable/valid bit */
+#define PSIHB_BBAR 0x00
+
+/* FSP MMIO region -- this is where the mbx regs are (offset defined below) */
+#define PSIHB_FSPBAR 0x08
+
+/* FSP MMIO region mask register -- determines size of region */
+#define PSIHB_FSPMMR 0x10
+
+/* TCE address register */
+#define PSIHB_TAR 0x18
+#define PSIHB_TAR_8K_ENTRIES 0
+#define PSIHB_TAR_16K_ENTRIES 1
+#define PSIHB_TAR_256K_ENTRIES 2 /* P8 only */
+#define PSIHB_TAR_512K_ENTRIES 4 /* P8 only */
+
+/* PSI Host Bridge Control Register
+ *
+ * note: TCE_ENABLE moved to the new PSIHB_PHBSCR on P8 but is
+ * the same bit position
+ */
+#define PSIHB_CR 0x20
+#define PSIHB_CR_FSP_CMD_ENABLE PPC_BIT(0)
+#define PSIHB_CR_FSP_MMIO_ENABLE PPC_BIT(1)
+#define PSIHB_CR_TCE_ENABLE PPC_BIT(2) /* P7 only */
+#define PSIHB_CR_FSP_IRQ_ENABLE PPC_BIT(3)
+#define PSIHB_CR_FSP_ERR_RSP_ENABLE PPC_BIT(4)
+#define PSIHB_CR_PSI_LINK_ENABLE PPC_BIT(5)
+#define PSIHB_CR_FSP_RESET PPC_BIT(6)
+#define PSIHB_CR_PSIHB_RESET PPC_BIT(7)
+#define PSIHB_CR_PSI_IRQ PPC_BIT(16) /* PSIHB interrupt */
+#define PSIHB_CR_FSP_IRQ PPC_BIT(17) /* FSP interrupt */
+#define PSIHB_CR_FSP_LINK_ACTIVE PPC_BIT(18) /* FSP link active */
+
+/* Error conditions in the GXHB */
+#define PSIHB_CR_PSI_ERROR PPC_BIT(32) /* PSI error */
+#define PSIHB_CR_PSI_LINK_INACTIVE PPC_BIT(33) /* Link inactive */
+#define PSIHB_CR_FSP_ACK_TIMEOUT PPC_BIT(34) /* FSP ack timeout */
+#define PSIHB_CR_MMIO_LOAD_TIMEOUT PPC_BIT(35) /* MMIO load timeout */
+#define PSIHB_CR_MMIO_LENGTH_ERROR PPC_BIT(36) /* MMIO length error */
+#define PSIHB_CR_MMIO_ADDRESS_ERROR PPC_BIT(37) /* MMIO address error */
+#define PSIHB_CR_MMIO_TYPE_ERROR PPC_BIT(38) /* MMIO type error */
+#define PSIHB_CR_UE PPC_BIT(39) /* UE detected */
+#define PSIHB_CR_PARITY_ERROR PPC_BIT(40) /* Parity error */
+#define PSIHB_CR_SYNC_ERR_ALERT1 PPC_BIT(41) /* Sync alert 1 */
+#define PSIHB_CR_SYNC_ERR_ALERT2 PPC_BIT(42) /* Sync alert 2 */
+#define PSIHB_CR_FSP_COMMAND_ERROR PPC_BIT(43) /* FSP cmd error */
+
+/* PSI Status / Error Mask Register */
+#define PSIHB_SEMR 0x28
+
+/* XIVR and BUID used for PSI interrupts on P7 */
+#define PSIHB_XIVR 0x30
+
+/* XIVR and BUID used for PSI interrupts on P8 */
+#define PSIHB_XIVR_FSP 0x30
+#define PSIHB_XIVR_OCC 0x60
+#define PSIHB_XIVR_FSI 0x68
+#define PSIHB_XIVR_LPC 0x70
+#define PSIHB_XIVR_LOCAL_ERR 0x78
+#define PSIHB_XIVR_HOST_ERR 0x80
+#define PSIHB_ISRN 0x88
+#define PSIHB_ISRN_COMP_MASK PPC_BITMASK(0,18)
+#define PSIHB_ISRN_COMP_LSH PPC_BITLSHIFT(18)
+#define PSIHB_ISRN_IRQ_MUX PPC_BIT(28)
+#define PSIHB_ISRN_IRQ_RESET PPC_BIT(29)
+#define PSIHB_ISRN_DOWNSTREAM_EN PPC_BIT(30)
+#define PSIHB_ISRN_UPSTREAM_EN PPC_BIT(31)
+#define PSIHB_ISRN_MASK_MASK PPC_BITMASK(32,50)
+#define PSIHB_ISRN_MASK_LSH PPC_BITLSHIFT(50)
+
+#define PSIHB_IRQ_STATUS 0x58
+#define PSIHB_IRQ_STAT_OCC PPC_BIT(27)
+#define PSIHB_IRQ_STAT_FSI PPC_BIT(28)
+#define PSIHB_IRQ_STAT_LPC PPC_BIT(29)
+#define PSIHB_IRQ_STAT_LOCAL_ERR PPC_BIT(30)
+#define PSIHB_IRQ_STAT_HOST_ERR PPC_BIT(31)
+
+/* Secure version of CR for P8 (TCE enable bit) */
+#define PSIHB_PHBSCR 0x90
+
+/*
+ * PSI Host Bridge Registers (XSCOM)
+ */
+#define PSIHB_XSCOM_P7_HBBAR 0x9
+#define PSIHB_XSCOM_P7_HBBAR_EN PPC_BIT(28)
+#define PSIHB_XSCOM_P7_HBCSR 0xd
+#define PSIHB_XSCOM_P7_HBCSR_SET 0x11
+#define PSIHB_XSCOM_P7_HBCSR_CLR 0x12
+#define PSIHB_XSCOM_P7_HBSCR_FSP_IRQ PPC_BIT(13)
+
+#define PSIHB_XSCOM_P8_BASE 0xa
+#define PSIHB_XSCOM_P8_HBBAR_EN PPC_BIT(63)
+#define PSIHB_XSCOM_P8_HBCSR 0xe
+#define PSIHB_XSCOM_P8_HBCSR_SET 0x12
+#define PSIHB_XSCOM_P8_HBCSR_CLR 0x13
+#define PSIHB_XSCOM_P8_HBSCR_FSP_IRQ PPC_BIT(17)
+
+
+/*
+ * Layout of the PSI DMA address space
+ *
+ * On P7, we instanciate a TCE table of 16K TCEs mapping 64M
+ *
+ * On P8, we use a larger mapping of 256K TCEs which provides
+ * us with a 1G window in order to fit the trace buffers
+ *
+ * Currently we have:
+ *
+ * - 4x256K serial areas (each divided in 2: in and out buffers)
+ * - 1M region for inbound buffers
+ * - 2M region for generic data fetches
+ */
+#define PSI_DMA_SER0_BASE 0x00000000
+#define PSI_DMA_SER0_SIZE 0x00040000
+#define PSI_DMA_SER1_BASE 0x00040000
+#define PSI_DMA_SER1_SIZE 0x00040000
+#define PSI_DMA_SER2_BASE 0x00080000
+#define PSI_DMA_SER2_SIZE 0x00040000
+#define PSI_DMA_SER3_BASE 0x000c0000
+#define PSI_DMA_SER3_SIZE 0x00040000
+#define PSI_DMA_INBOUND_BUF 0x00100000
+#define PSI_DMA_INBOUND_SIZE 0x00100000
+#define PSI_DMA_FETCH 0x00200000
+#define PSI_DMA_FETCH_SIZE 0x00800000
+#define PSI_DMA_NVRAM_BODY 0x00a00000
+#define PSI_DMA_NVRAM_BODY_SZ 0x00100000
+#define PSI_DMA_NVRAM_TRIPL 0x00b00000
+#define PSI_DMA_NVRAM_TRIPL_SZ 0x00001000
+#define PSI_DMA_OP_PANEL_MISC 0x00b01000
+#define PSI_DMA_OP_PANEL_SIZE 0x00001000
+#define PSI_DMA_GET_SYSPARAM 0x00b02000
+#define PSI_DMA_GET_SYSPARAM_SZ 0x00001000
+#define PSI_DMA_SET_SYSPARAM 0x00b03000
+#define PSI_DMA_SET_SYSPARAM_SZ 0x00001000
+#define PSI_DMA_ERRLOG_READ_BUF 0x00b04000
+#define PSI_DMA_ERRLOG_READ_BUF_SZ 0x00040000
+#define PSI_DMA_ELOG_PANIC_WRITE_BUF 0x00b44000
+#define PSI_DMA_ELOG_PANIC_WRITE_BUF_SZ 0x00010000
+#define PSI_DMA_ERRLOG_WRITE_BUF 0x00b54000
+#define PSI_DMA_ERRLOG_WRITE_BUF_SZ 0x00050000
+#define PSI_DMA_HBRT_LOG_WRITE_BUF 0x00ba4000
+#define PSI_DMA_HBRT_LOG_WRITE_BUF_SZ 0x00001000
+#define PSI_DMA_CODE_UPD 0x00c04000
+#define PSI_DMA_CODE_UPD_SIZE 0x01001000
+#define PSI_DMA_DUMP_DATA 0x01c05000
+#define PSI_DMA_DUMP_DATA_SIZE 0x00500000
+#define PSI_DMA_SENSOR_BUF 0x02105000
+#define PSI_DMA_SENSOR_BUF_SZ 0x00080000
+#define PSI_DMA_MDST_TABLE 0x02185000
+#define PSI_DMA_MDST_TABLE_SIZE 0x00001000
+#define PSI_DMA_HYP_DUMP 0x02186000
+#define PSI_DMA_HYP_DUMP_SIZE 0x01000000
+#define PSI_DMA_PCIE_INVENTORY 0x03186000
+#define PSI_DMA_PCIE_INVENTORY_SIZE 0x00010000
+#define PSI_DMA_LED_BUF 0x03196000
+#define PSI_DMA_LED_BUF_SZ 0x00001000
+#define PSI_DMA_LOC_COD_BUF 0x03197000
+#define PSI_DMA_LOC_COD_BUF_SZ 0x00008000
+#define PSI_DMA_MEMCONS 0x0319f000
+#define PSI_DMA_MEMCONS_SZ 0x00001000
+#define PSI_DMA_LOG_BUF 0x03200000
+#define PSI_DMA_LOG_BUF_SZ 0x00100000 /* INMEM_CON_LEN */
+
+/* P8 only mappings */
+#define PSI_DMA_TRACE_BASE 0x04000000
+
+struct psi {
+ struct list_node list;
+ uint64_t xscom_base;
+ void *regs;
+ unsigned int chip_id;
+ unsigned int interrupt;
+ bool working;
+ bool active;
+};
+
+extern void psi_set_link_polling(bool active);
+
+extern struct psi *first_psi;
+extern void psi_init(void);
+extern struct psi *psi_find_link(uint32_t chip_id);
+extern void psi_init_for_fsp(struct psi *psi);
+extern void psi_disable_link(struct psi *psi);
+extern bool psi_check_link_active(struct psi *psi);
+extern bool psi_poll_fsp_interrupt(struct psi *psi);
+
+/* Interrupts */
+extern void psi_irq_reset(void);
+extern void psi_enable_fsp_interrupt(struct psi *psi);
+extern void psi_fsp_link_in_use(struct psi *psi);
+
+/*
+ * Must be called by the platform probe() function as the policy
+ * is established before platform.init
+ *
+ * This defines whether the external interrupt should be passed to
+ * the OS or handled locally in skiboot. Return true for skiboot
+ * handling. Default if not called is Linux.
+ */
+#define EXTERNAL_IRQ_POLICY_LINUX false
+#define EXTERNAL_IRQ_POLICY_SKIBOOT true
+extern void psi_set_external_irq_policy(bool policy);
+
+
+
+#endif /* __PSI_H */
diff --git a/include/sfc-ctrl.h b/include/sfc-ctrl.h
new file mode 100644
index 0000000..8ff9780
--- /dev/null
+++ b/include/sfc-ctrl.h
@@ -0,0 +1,24 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef SFC_CTRL_H
+#define SFC_CTRL_H
+
+struct spi_flash_ctrl;
+
+extern int sfc_open(struct spi_flash_ctrl **ctrl);
+extern void sfc_close(struct spi_flash_ctrl *ctrl);
+
+#endif /* SFC_CTRL_H */
diff --git a/include/skiboot.h b/include/skiboot.h
new file mode 100644
index 0000000..c5b1fe0
--- /dev/null
+++ b/include/skiboot.h
@@ -0,0 +1,202 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SKIBOOT_H
+#define __SKIBOOT_H
+
+#include <compiler.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <bitutils.h>
+#include <types.h>
+
+#include <ccan/container_of/container_of.h>
+#include <ccan/list/list.h>
+#include <ccan/short_types/short_types.h>
+#include <ccan/build_assert/build_assert.h>
+#include <ccan/array_size/array_size.h>
+#include <ccan/endian/endian.h>
+#include <ccan/str/str.h>
+
+#include <mem-map.h>
+#include <op-panel.h>
+#include <platform.h>
+
+/* Special ELF sections */
+#define __force_data __section(".force.data")
+
+/* Readonly section start and end. */
+extern char __rodata_start[], __rodata_end[];
+
+static inline bool is_rodata(const void *p)
+{
+ return ((const char *)p >= __rodata_start && (const char *)p < __rodata_end);
+}
+
+/* Debug descriptor. This structure is pointed to by the word at offset
+ * 0x80 in the sapphire binary
+ */
+struct debug_descriptor {
+ u8 eye_catcher[8]; /* "OPALdbug" */
+#define DEBUG_DESC_VERSION 1
+ u32 version;
+ u32 reserved[3];
+
+ /* Memory console */
+ u64 memcons_phys;
+ u32 memcons_tce;
+ u32 memcons_obuf_tce;
+ u32 memcons_ibuf_tce;
+
+ /* Traces */
+ u64 trace_mask;
+ u32 num_traces;
+#define DEBUG_DESC_MAX_TRACES 256
+ u64 trace_phys[DEBUG_DESC_MAX_TRACES];
+ u32 trace_size[DEBUG_DESC_MAX_TRACES];
+ u32 trace_tce[DEBUG_DESC_MAX_TRACES];
+};
+extern struct debug_descriptor debug_descriptor;
+
+/* General utilities */
+#define prerror(fmt...) do { fprintf(stderr, fmt); } while(0)
+
+/* Location codes -- at most 80 chars with null termination */
+#define LOC_CODE_SIZE 80
+
+enum ipl_state {
+ ipl_initial = 0x00000000,
+ ipl_opl_sent = 0x00000001,
+ ipl_got_continue = 0x00000002,
+ ipl_got_new_role = 0x00000004,
+ ipl_got_caps = 0x00000008,
+ ipl_got_fsp_functional = 0x00000010
+};
+extern enum ipl_state ipl_state;
+
+/* Processor generation */
+enum proc_gen {
+ proc_gen_unknown,
+ proc_gen_p7, /* P7 and P7+ */
+ proc_gen_p8,
+};
+extern enum proc_gen proc_gen;
+
+/* Boot stack top */
+extern void *boot_stack_top;
+
+/* For use by debug code */
+extern void backtrace(void);
+
+/* Convert a 4-bit number to a hex char */
+extern char tohex(uint8_t nibble);
+
+/* Bit position of the most significant 1-bit (LSB=0, MSB=63) */
+static inline int ilog2(unsigned long val)
+{
+ int left_zeros;
+
+ asm volatile ("cntlzd %0,%1" : "=r" (left_zeros) : "r" (val));
+
+ return 63 - left_zeros;
+}
+
+static inline bool is_pow2(unsigned long val)
+{
+ return val == (1ul << ilog2(val));
+}
+
+#define lo32(x) ((x) & 0xffffffff)
+#define hi32(x) (((x) >> 32) & 0xffffffff)
+
+/* WARNING: _a *MUST* be a power of two */
+#define ALIGN_UP(_v, _a) (((_v) + (_a) - 1) & ~((_a) - 1))
+#define ALIGN_DOWN(_v, _a) ((_v) & ~((_a) - 1))
+
+/* TCE alignment */
+#define TCE_PSIZE 0x1000
+
+/* Not the greatest variants but will do for now ... */
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+/* Clean the stray high bit which the FSP inserts: we only have 52 bits real */
+static inline u64 cleanup_addr(u64 addr)
+{
+ return addr & ((1ULL << 52) - 1);
+}
+
+/* Start the kernel */
+extern void start_kernel(uint64_t entry, void* fdt,
+ uint64_t mem_top) __noreturn;
+extern void start_kernel32(uint64_t entry, void* fdt,
+ uint64_t mem_top) __noreturn;
+extern void start_kernel_secondary(uint64_t entry) __noreturn;
+
+/* Get description of machine from HDAT and create device-tree */
+extern void parse_hdat(bool is_opal, uint32_t master_cpu);
+
+/* Root of device tree. */
+extern struct dt_node *dt_root;
+
+/* Generated git id. */
+extern const char gitid[];
+
+/* Fast reboot support */
+extern void fast_reset(void);
+extern void __secondary_cpu_entry(void);
+extern void load_and_boot_kernel(bool is_reboot);
+extern void cleanup_tlb(void);
+extern void init_shared_sprs(void);
+extern void init_replicated_sprs(void);
+
+/* Various probe routines, to replace with an initcall system */
+extern void probe_p5ioc2(void);
+extern void probe_p7ioc(void);
+extern void probe_phb3(void);
+extern void uart_init(bool enable_interrupt);
+extern void homer_init(void);
+extern void add_cpu_idle_state_properties(void);
+extern void occ_pstates_init(void);
+extern void slw_init(void);
+extern void occ_fsp_init(void);
+
+/* NVRAM support */
+extern void nvram_init(void);
+extern void nvram_read_complete(bool success);
+
+/* NVRAM on flash helper */
+struct flash_chip;
+extern int flash_nvram_init(struct flash_chip *chip, uint32_t start,
+ uint32_t size);
+
+/* UART interrupt */
+extern void uart_irq(void);
+
+/* Flatten device-tree */
+extern void *create_dtb(const struct dt_node *root);
+
+/* SLW reinit function for switching core settings */
+extern int64_t slw_reinit(uint64_t flags);
+
+
+#endif /* __SKIBOOT_H */
+
diff --git a/include/spcn.h b/include/spcn.h
new file mode 100644
index 0000000..1945e8d
--- /dev/null
+++ b/include/spcn.h
@@ -0,0 +1,93 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ */
+
+
+#ifndef __SPCN_H
+#define __SPCN_H
+
+
+/* SPCN commands */
+#define SPCN_CMD_PRS 0x42 /* Power Resource Status */
+#define SPCN_CMD_SET 0x66 /* Set Environmental Thresholds */
+
+/* SPCN command address modes */
+#define SPCN_ADDR_MODE_CEC_NODE 0x0000d000 /* CEC node single destination */
+#define SPCN_ADDR_MODE_ALL_SLAVES 0x0000f000 /* Address all slaves in all racks */
+#define SPCN_ADDR_MODE_RACK_NODES 0x00000000 /* Address rack node in all racks */
+
+/* SPCN PRS command modifiers */
+#define SPCN_MOD_PRS_STATUS_FIRST 0x01 /* Power Resource Status (First 1KB) */
+#define SPCN_MOD_PRS_STATUS_SUBS 0x02 /* Subsequent set of 1KB PRS entries */
+#define SPCN_MOD_PRS_LED_DATA_FIRST 0x51 /* LED data entry (First 1KB) */
+#define SPCN_MOD_PRS_LED_DATA_SUB 0x52 /* Subsequent LED data entries */
+
+/* SPCN SET command modifiers */
+#define SPCN_MOD_SET_LED_CTL_LOC_CODE 0x07 /* Control LED with location code */
+#define SPCN_MOD_SET_IDENTIFY_OFF_ENC 0x08 /* Turn off identify LEDs in CEC */
+#define SPCN_MOD_SET_IDENTIFY_OFF_NODE 0x0B /* Turn off identify LEDs in Node */
+
+/* SPCN SENSOR command modifiers */
+#define SPCN_MOD_SENSOR_PARAM_FIRST 0x10 /* First 1K sensor parameters */
+#define SPCN_MOD_SENSOR_PARAM_SUBS 0x11 /* Subsequent sensor parameters */
+#define SPCN_MOD_SENSOR_DATA_FIRST 0x12 /* First 1K sensor data */
+#define SPCN_MOD_SENSOR_DATA_SUBS 0x13 /* Subsequent sensor data blocks */
+#define SPCN_MOD_PROC_JUNC_TEMP 0x14 /* Process junction temperatures */
+#define SPCN_MOD_SENSOR_POWER 0x1c /* System power consumption */
+#define SPCN_MOD_LAST 0xff
+
+/*
+ * Modifiers 0x53 and 0x54 are used by LEDS at standby. So HV does not come into
+ * the picture here. Do we need those?
+ */
+
+/* Supported SPCN response codes */
+#define LOGICAL_IND_STATE_MASK 0x10 /* If set, control fault state */
+#define ACTIVE_LED_STATE_MASK 0x01 /* If set, switch on the LED */
+#define SPCN_LED_IDENTIFY_MASK 0x80 /* Set identify indicator */
+#define SPCN_LED_FAULT_MASK 0x40 /* Set fault indicator */
+#define SPCN_LED_TRANS_MASK 0x20 /* LED is in transition */
+#define SPCN_CLR_LED_STATE 0x00 /* Reset identify indicator */
+
+/* SPCN command response status codes */
+enum spcn_rsp_status {
+ SPCN_RSP_STATUS_SUCCESS = 0x01, /* Command successful */
+ SPCN_RSP_STATUS_COND_SUCCESS = 0x02, /* Command successful, but additional entries exist */
+ SPCN_RSP_STATUS_INVALID_RACK = 0x15, /* Invalid rack command */
+ SPCN_RSP_STATUS_INVALID_SLAVE = 0x16, /* Invalid slave command */
+ SPCN_RSP_STATUS_INVALID_MOD = 0x18, /* Invalid modifier */
+ SPCN_RSP_STATUS_STATE_PROHIBIT = 0x21, /* Present state prohibits */
+ SPCN_RSP_STATUS_UNKNOWN = 0xff, /* Default state */
+};
+
+/* Sensor FRCs (Frame resource class) */
+enum {
+ SENSOR_FRC_POWER_CTRL = 0x02,
+ SENSOR_FRC_POWER_SUPPLY,
+ SENSOR_FRC_REGULATOR,
+ SENSOR_FRC_COOLING_FAN,
+ SENSOR_FRC_COOLING_CTRL,
+ SENSOR_FRC_BATTERY_CHRG,
+ SENSOR_FRC_BATTERY_PACK,
+ SENSOR_FRC_AMB_TEMP,
+ SENSOR_FRC_TEMP,
+ SENSOR_FRC_VRM,
+ SENSOR_FRC_RISER_CARD,
+ SENSOR_FRC_IO_BP,
+};
+
+#endif /* __SPCN_H */
diff --git a/include/stack.h b/include/stack.h
new file mode 100644
index 0000000..6eedc01
--- /dev/null
+++ b/include/stack.h
@@ -0,0 +1,92 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __STACKFRAME_H
+#define __STACKFRAME_H
+
+#define STACK_ENTRY_OPAL_API 0 /* OPAL call */
+#define STACK_ENTRY_MCHECK 0x0200 /* Machine check */
+#define STACK_ENTRY_HMI 0x0e60 /* Hypervisor maintainance */
+#define STACK_ENTRY_RESET 0x0100 /* System reset */
+#define STACK_ENTRY_SOFTPATCH 0x1500 /* Soft patch (denorm emulation) */
+
+/* Portion of the stack reserved for machine checks */
+#define MC_STACK_SIZE 0x1000
+
+/* Safety/ABI gap at top of stack */
+#define STACK_TOP_GAP 0x100
+
+/* Remaining stack space (gap included) */
+#define NORMAL_STACK_SIZE (STACK_SIZE - MC_STACK_SIZE)
+
+/* Offset to get to normal CPU stacks */
+#define CPU_STACKS_OFFSET (CPU_STACKS_BASE + \
+ NORMAL_STACK_SIZE - STACK_TOP_GAP)
+
+/* Offset to get to machine check CPU stacks */
+#define CPU_MC_STACKS_OFFSET (CPU_STACKS_BASE + STACK_SIZE - STACK_TOP_GAP)
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+/* This is the struct used to save GPRs etc.. on OPAL entry
+ * and from some exceptions. It is not always entirely populated
+ * depending on the entry type
+ */
+struct stack_frame {
+ /* Standard 112-byte stack frame header (the minimum size required,
+ * using an 8-doubleword param save area). The callee (in C) may use
+ * lrsave; we declare these here so we don't get our own save area
+ * overwritten */
+ uint64_t backchain;
+ uint64_t crsave;
+ uint64_t lrsave;
+ uint64_t compiler_dw;
+ uint64_t linker_dw;
+ uint64_t tocsave;
+ uint64_t paramsave[8];
+
+ /* Space for stack-local vars used by asm. At present we only use
+ * one doubleword. */
+ uint64_t locals[1];
+
+ /* Entry type */
+ uint64_t type;
+
+ /* GPR save area
+ *
+ * We don't necessarily save everything in here
+ */
+ uint64_t gpr[32];
+
+ /* Other SPR saved
+ *
+ * Only for some exceptions.
+ */
+ uint32_t cr;
+ uint32_t xer;
+ uint64_t ctr;
+ uint64_t lr;
+ uint64_t pc;
+ uint64_t cfar;
+ uint64_t srr0;
+ uint64_t srr1;
+} __attribute__((aligned(16)));
+
+#endif /* __ASSEMBLY__ */
+#endif /* __STACKFRAME_H */
+
diff --git a/include/timebase.h b/include/timebase.h
new file mode 100644
index 0000000..11ab126
--- /dev/null
+++ b/include/timebase.h
@@ -0,0 +1,91 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Timebase helpers.
+ *
+ * Note: Only use after the TODs are in sync !
+ */
+#ifndef __TIME_H
+#define __TIME_H
+
+#include <time.h>
+
+static inline unsigned long mftb(void)
+{
+ unsigned long tb;
+
+ /* We use a memory clobber to avoid this being
+ * moved in the instruction stream
+ */
+ asm volatile("mftb %0" : "=r"(tb) : : "memory");
+ return tb;
+}
+
+enum tb_cmpval {
+ TB_ABEFOREB = -1,
+ TB_AEQUALB = 0,
+ TB_AAFTERB = 1
+};
+
+static inline enum tb_cmpval tb_compare(unsigned long a,
+ unsigned long b)
+{
+ if (a == b)
+ return TB_AEQUALB;
+ return ((long)(b - a)) > 0 ? TB_ABEFOREB : TB_AAFTERB;
+}
+
+/* Architected timebase */
+static const unsigned long tb_hz = 512000000;
+
+static inline unsigned long secs_to_tb(unsigned long secs)
+{
+ return secs * tb_hz;
+}
+
+static inline unsigned long msecs_to_tb(unsigned long msecs)
+{
+ return msecs * (tb_hz / 1000);
+}
+
+static inline unsigned long tb_to_msecs(unsigned long tb)
+{
+ return (tb * 1000) / tb_hz;
+}
+
+static inline unsigned long usecs_to_tb(unsigned long usecs)
+{
+ return usecs * (tb_hz / 1000000);
+}
+
+static inline unsigned long tb_to_usecs(unsigned long tb)
+{
+ return (tb * 1000000) / tb_hz;
+}
+
+extern unsigned long timespec_to_tb(const struct timespec *ts);
+
+/* wait_poll - Wait a certain number of TB ticks while polling FSP */
+extern void time_wait(unsigned long duration);
+
+/* wait_poll_ms - Wait a certain number of milliseconds while polling FSP */
+extern void time_wait_ms(unsigned long ms);
+
+/* wait_poll_us - Wait a certain number of microseconds while polling FSP */
+extern void time_wait_us(unsigned long us);
+
+#endif /* __TIME_H */
diff --git a/include/trace.h b/include/trace.h
new file mode 100644
index 0000000..da43572
--- /dev/null
+++ b/include/trace.h
@@ -0,0 +1,46 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TRACE_H
+#define __TRACE_H
+#include <ccan/short_types/short_types.h>
+#include <stddef.h>
+#include <lock.h>
+#include <trace_types.h>
+
+#define TBUF_SZ (1024 * 1024)
+
+struct cpu_thread;
+
+/* Here's one we prepared earlier. */
+void init_boot_tracebuf(struct cpu_thread *boot_cpu);
+
+struct trace_info {
+ /* Lock for writers. */
+ struct lock lock;
+ /* Exposed to kernel. */
+ struct tracebuf tb;
+};
+
+/* Allocate trace buffers once we know memory topology */
+void init_trace_buffers(void);
+
+/* This will fill in timestamp and cpu; you must do type and len. */
+void trace_add(union trace *trace, u8 type, u16 len);
+
+/* Put trace node into dt. */
+void trace_add_node(void);
+#endif /* __TRACE_H */
diff --git a/include/trace_types.h b/include/trace_types.h
new file mode 100644
index 0000000..d1d3690
--- /dev/null
+++ b/include/trace_types.h
@@ -0,0 +1,132 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* API for kernel to read trace buffer. */
+#ifndef __TRACE_TYPES_H
+#define __TRACE_TYPES_H
+
+#define TRACE_REPEAT 1
+#define TRACE_OVERFLOW 2
+#define TRACE_OPAL 3 /* OPAL call */
+#define TRACE_FSP_MSG 4 /* FSP message sent/received */
+#define TRACE_FSP_EVENT 5 /* FSP driver event */
+#define TRACE_UART 6 /* UART driver traces */
+
+/* One per cpu, plus one for NMIs */
+struct tracebuf {
+ /* Mask to apply to get buffer offset. */
+ u64 mask;
+ /* This where the buffer starts. */
+ u64 start;
+ /* This is where writer has written to. */
+ u64 end;
+ /* This is where the writer wrote to previously. */
+ u64 last;
+ /* This is where the reader is up to. */
+ u64 rpos;
+ /* If the last one we read was a repeat, this shows how many. */
+ u32 last_repeat;
+ /* Maximum possible size of a record. */
+ u32 max_size;
+
+ char buf[/* TBUF_SZ + max_size */];
+};
+
+/* Common header for all trace entries. */
+struct trace_hdr {
+ u64 timestamp;
+ u8 type;
+ u8 len_div_8;
+ u16 cpu;
+ u8 unused[4];
+};
+
+/* Note: all other entries must be at least as large as this! */
+struct trace_repeat {
+ u64 timestamp; /* Last repeat happened at this timestamp */
+ u8 type; /* == TRACE_REPEAT */
+ u8 len_div_8;
+ u16 cpu;
+ u16 prev_len;
+ u16 num; /* Starts at 1, ie. 1 repeat, or two traces. */
+ /* Note that the count can be one short, if read races a repeat. */
+};
+
+/* Overflow is special */
+struct trace_overflow {
+ u64 unused64; /* Timestamp is unused */
+ u8 type; /* == TRACE_OVERFLOW */
+ u8 len_div_8;
+ u8 unused[6]; /* ie. hdr.cpu is indeterminate */
+ u64 bytes_missed;
+};
+
+/* All other trace types have a full header */
+struct trace_opal {
+ struct trace_hdr hdr;
+ u64 token, lr, sp, r3_to_11[9];
+};
+
+#define TRACE_FSP_MSG_IN 0
+#define TRACE_FSP_MSG_OUT 1
+
+struct trace_fsp_msg {
+ struct trace_hdr hdr;
+ u32 word0;
+ u32 word1;
+ u8 dlen;
+ u8 dir; /* TRACE_FSP_MSG_IN or TRACE_FSP_MSG_OUT */
+ u8 data[56]; /* See dlen, but max is 56 bytes. */
+};
+
+#define TRACE_FSP_EVT_LINK_DOWN 0
+#define TRACE_FSP_EVT_DISR_CHG 1 /* 0:disr */
+#define TRACE_FSP_EVT_SOFT_RR 2 /* 0:disr */
+#define TRACE_FSP_EVT_RR_COMPL 3
+#define TRACE_FSP_EVT_HDES_CHG 4 /* 0:hdes */
+#define TRACE_FSP_EVT_POLL_IRQ 5 /* 0:irq? 1:hdir 2:ctl 3:psi_irq */
+
+struct trace_fsp_event {
+ struct trace_hdr hdr;
+ u16 event;
+ u16 fsp_state;
+ u32 data[4]; /* event type specific */
+};
+
+#define TRACE_UART_CTX_IRQ 0
+#define TRACE_UART_CTX_POLL 1
+#define TRACE_UART_CTX_READ 2
+
+struct trace_uart {
+ struct trace_hdr hdr;
+ u8 ctx;
+ u8 cnt;
+ u8 irq_state;
+ u8 unused;
+ u16 in_count;
+};
+
+union trace {
+ struct trace_hdr hdr;
+ /* Trace types go here... */
+ struct trace_repeat repeat;
+ struct trace_overflow overflow;
+ struct trace_opal opal;
+ struct trace_fsp_msg fsp_msg;
+ struct trace_fsp_event fsp_evt;
+ struct trace_uart uart;
+};
+
+#endif /* __TRACE_TYPES_H */
diff --git a/include/types.h b/include/types.h
new file mode 100644
index 0000000..36dc81d
--- /dev/null
+++ b/include/types.h
@@ -0,0 +1,27 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TYPES_H
+#define __TYPES_H
+#include <ccan/short_types/short_types.h>
+
+/* These are currently just for clarity, but we could apply sparse. */
+typedef u16 __be16;
+typedef u32 __be32;
+typedef u64 __be64;
+
+#endif /* __TYPES_H */
+
diff --git a/include/vpd.h b/include/vpd.h
new file mode 100644
index 0000000..c49ab71
--- /dev/null
+++ b/include/vpd.h
@@ -0,0 +1,45 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __VPD_H
+#define __VPD_H
+
+struct machine_info {
+ const char *mtm;
+ const char *name;
+};
+
+const struct machine_info *machine_info_lookup(char *mtm);
+
+const void *vpd_find_keyword(const void *rec, size_t rec_sz,
+ const char *kw, uint8_t *kw_size);
+
+const void *vpd_find_record(const void *vpd, size_t vpd_size,
+ const char *record, size_t *sz);
+
+const void *vpd_find(const void *vpd, size_t vpd_size,
+ const char *record, const char *keyword,
+ uint8_t *sz);
+
+/* Add model property to dt_root */
+void add_dtb_model(void);
+
+void vpd_iohub_load(struct dt_node *hub_node);
+
+#define VPD_LOAD_LXRN_VINI 0xff
+
+
+#endif /* __VPD_H */
diff --git a/include/xscom.h b/include/xscom.h
new file mode 100644
index 0000000..2b09a86
--- /dev/null
+++ b/include/xscom.h
@@ -0,0 +1,171 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __XSCOM_H
+#define __XSCOM_H
+
+#include <stdint.h>
+#include <processor.h>
+#include <cpu.h>
+
+/*
+ * SCOM "partID" definitions:
+ *
+ * All Ids are 32-bits long, top nibble is reserved for the
+ * 'type' field:
+ * 0x0 = Processor Chip
+ * 0x8 = Memory Buffer (Centaur) Chip
+ * 0x4 = EX/Core Chiplet
+ *
+ * Processor Chip = Logical Fabric Id = PIR>>7
+ * 0b0000.0000.0000.0000.0000.0000.00NN.NCCC
+ * N=Node, C=Chip
+ * Centaur Chip = Associated Processor Chip with memory channel
+ * appended and flag set
+ * 0b1000.0000.0000.0000.0000.00NN.NCCC.MMMM
+ * N=Node, C=Chip, M=Memory Channel
+ * Processor EX/Core chiplet = PIR >> 3 with flag set
+ * 0b0100.0000.0000.0000.0000.00NN.NCCC.PPPP
+ * N=Node, C=Chip, P=Processor core
+ */
+
+/*
+ * SCOM Address definition extracted from HWPs for documentation
+ * purposes
+ *
+ * "Normal" (legacy) format
+ *
+ * 111111 11112222 22222233 33333333 44444444 44555555 55556666
+ * 01234567 89012345 67890123 45678901 23456789 01234567 89012345 67890123
+ * -------- -------- -------- -------- -------- -------- -------- --------
+ * 00000000 00000000 00000000 00000000 0MCCCCCC ????PPPP 00LLLLLL LLLLLLLL
+ * || | |
+ * || | `-> Local Address*
+ * || |
+ * || `-> Port
+ * ||
+ * |`-> Chiplet ID**
+ * |
+ * `-> Multicast bit
+ *
+ * * Local address is composed of "00" + 4-bit ring + 10-bit ID
+ * The 10-bit ID is usually 4-bit sat_id and 6-bit reg_id
+ *
+ * ** Chiplet ID turns into multicast operation type and group number
+ * if the multicast bit is set
+ *
+ * "Indirect" format
+ *
+ *
+ * 111111 11112222 22222233 33333333 44444444 44555555 55556666
+ * 01234567 89012345 67890123 45678901 23456789 01234567 89012345 67890123
+ * -------- -------- -------- -------- -------- -------- -------- --------
+ * 10000000 0000IIII IIIIIGGG GGGLLLLL 0MCCCCCC ????PPPP 00LLLLLL LLLLLLLL
+ * | | | || | |
+ * | | | || | `-> Local Address*
+ * | | | || |
+ * | | | || `-> Port
+ * | | | ||
+ * | | | |`-> Chiplet ID**
+ * | | | |
+ * | | | `-> Multicast bit
+ * | | |
+ * | | `-> Lane ID
+ * | |
+ * | `-> RX or TX Group ID
+ * |
+ * `-> Indirect Register Address
+ *
+ * * Local address is composed of "00" + 4-bit ring + 4-bit sat_id + "111111"
+ *
+ * ** Chiplet ID turns into multicast operation type and group number
+ * if the multicast bit is set
+ */
+
+/*
+ * Generate a local address from a given ring/satellite/offset
+ * combination:
+ *
+ * Ring Satelite offset
+ * +---------+---------+-------------+
+ * | 4 | 4 | 6 |
+ * +---------+---------+-------------+
+ */
+#define XSCOM_SAT(_r, _s, _o) \
+ (((_r) << 10) | ((_s) << 6) | (_o))
+
+/*
+ * Additional useful definitions
+ */
+#define P8_EX_PCB_SLAVE_BASE 0x100F0000
+
+#define XSCOM_ADDR_P8_EX_SLAVE(core, offset) \
+ (P8_EX_PCB_SLAVE_BASE | (((core) & 0xF) << 24) | ((offset) & 0xFFFF))
+
+#define XSCOM_ADDR_P8_EX(core, addr) \
+ ((((core) & 0xF) << 24) | (addr))
+
+/* Per core power mgt registers */
+#define PM_OHA_MODE_REG 0x1002000D
+
+/* EX slave per-core power mgt slave regisers */
+#define EX_PM_GP0 0x0100
+#define EX_PM_GP1 0x0103
+#define EX_PM_SPECIAL_WAKEUP_FSP 0x010B
+#define EX_PM_SPECIAL_WAKEUP_OCC 0x010C
+#define EX_PM_SPECIAL_WAKEUP_PHYP 0x010D
+#define EX_PM_IDLE_STATE_HISTORY_PHYP 0x0110
+#define EX_PM_IDLE_STATE_HISTORY_FSP 0x0111
+#define EX_PM_IDLE_STATE_HISTORY_OCC 0x0112
+#define EX_PM_IDLE_STATE_HISTORY_PERF 0x0113
+#define EX_PM_CORE_PFET_VRET 0x0130
+#define EX_PM_CORE_ECO_VRET 0x0150
+#define EX_PM_PPMSR 0x0153
+#define EX_PM_PPMCR 0x0159
+
+/* Power mgt bits in GP0 */
+#define EX_PM_GP0_SPECIAL_WAKEUP_DONE PPC_BIT(31)
+
+/* Power mgt settings in GP1 */
+#define EX_PM_SETUP_GP1_FAST_SLEEP 0xD820000000000000ULL
+#define EX_PM_SETUP_GP1_DEEP_SLEEP 0x2420000000000000ULL
+#define EX_PM_SETUP_GP1_PM_SPR_OVERRIDE_EN 0x0010000000000000ULL
+#define EX_PM_SETUP_GP1_DPLL_FREQ_OVERRIDE_EN 0x0020000000000000ULL
+
+/* Fields in history regs */
+#define EX_PM_IDLE_ST_HIST_PM_STATE_MASK PPC_BITMASK(0, 2)
+#define EX_PM_IDLE_ST_HIST_PM_STATE_LSH PPC_BITLSHIFT(2)
+
+
+/*
+ * Error handling:
+ *
+ * Error codes TBD, 0 = success
+ */
+
+/* Targeted SCOM access */
+extern int xscom_read(uint32_t partid, uint64_t pcb_addr, uint64_t *val);
+extern int xscom_write(uint32_t partid, uint64_t pcb_addr, uint64_t val);
+
+/* This chip SCOM access */
+extern int xscom_readme(uint64_t pcb_addr, uint64_t *val);
+extern int xscom_writeme(uint64_t pcb_addr, uint64_t val);
+extern void xscom_init(void);
+
+/* Mark XSCOM lock as being in console path */
+extern void xscom_used_by_console(void);
+
+#endif /* __XSCOM_H */