From 1d880992fd8c8457a2d990ac6622cfd58fb1b261 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 2 Jul 2014 15:36:20 +1000 Subject: Initial commit of Open Source release Signed-off-by: Benjamin Herrenschmidt --- include/affinity.h | 34 ++ include/asm-utils.h | 45 +++ include/ast.h | 78 ++++ include/bitutils.h | 50 +++ include/capp.h | 62 +++ include/cec.h | 51 +++ include/centaur.h | 24 ++ include/chip.h | 151 ++++++++ include/chiptod.h | 28 ++ include/codeupdate.h | 236 ++++++++++++ include/compiler.h | 50 +++ include/config.h | 93 +++++ include/console.h | 68 ++++ include/cpu.h | 207 ++++++++++ include/device.h | 233 +++++++++++ include/device_tree.h | 35 ++ include/ec/config.h | 82 ++++ include/ec/gpio.h | 53 +++ include/elf.h | 135 +++++++ include/fsi-master.h | 36 ++ include/fsp-elog.h | 325 ++++++++++++++++ include/fsp-leds.h | 135 +++++++ include/fsp-mdst-table.h | 37 ++ include/fsp-sysparam.h | 57 +++ include/fsp.h | 755 ++++++++++++++++++++++++++++++++++++ include/gx.h | 59 +++ include/hostservices.h | 36 ++ include/interrupts.h | 254 ++++++++++++ include/io.h | 175 +++++++++ include/lock.h | 83 ++++ include/lpc.h | 95 +++++ include/mem-map.h | 114 ++++++ include/mem_region-malloc.h | 41 ++ include/mem_region.h | 69 ++++ include/memory.h | 23 ++ include/nx.h | 22 ++ include/op-panel.h | 67 ++++ include/opal-internal.h | 234 ++++++++++++ include/opal-msg.h | 36 ++ include/opal.h | 912 ++++++++++++++++++++++++++++++++++++++++++++ include/p5ioc2-regs.h | 251 ++++++++++++ include/p5ioc2.h | 184 +++++++++ include/p7ioc-regs.h | 472 +++++++++++++++++++++++ include/p7ioc.h | 431 +++++++++++++++++++++ include/pci-cfg.h | 524 +++++++++++++++++++++++++ include/pci.h | 504 ++++++++++++++++++++++++ include/phb3-regs.h | 436 +++++++++++++++++++++ include/phb3.h | 355 +++++++++++++++++ include/platform.h | 122 ++++++ include/processor.h | 318 +++++++++++++++ include/psi.h | 239 ++++++++++++ include/sfc-ctrl.h | 24 ++ include/skiboot.h | 202 ++++++++++ include/spcn.h | 93 +++++ include/stack.h | 92 +++++ include/timebase.h | 91 +++++ include/trace.h | 46 +++ include/trace_types.h | 132 +++++++ include/types.h | 27 ++ include/vpd.h | 45 +++ include/xscom.h | 171 +++++++++ 61 files changed, 10039 insertions(+) create mode 100644 include/affinity.h create mode 100644 include/asm-utils.h create mode 100644 include/ast.h create mode 100644 include/bitutils.h create mode 100644 include/capp.h create mode 100644 include/cec.h create mode 100644 include/centaur.h create mode 100644 include/chip.h create mode 100644 include/chiptod.h create mode 100644 include/codeupdate.h create mode 100644 include/compiler.h create mode 100644 include/config.h create mode 100644 include/console.h create mode 100644 include/cpu.h create mode 100644 include/device.h create mode 100644 include/device_tree.h create mode 100644 include/ec/config.h create mode 100644 include/ec/gpio.h create mode 100644 include/elf.h create mode 100644 include/fsi-master.h create mode 100644 include/fsp-elog.h create mode 100644 include/fsp-leds.h create mode 100644 include/fsp-mdst-table.h create mode 100644 include/fsp-sysparam.h create mode 100644 include/fsp.h create mode 100644 include/gx.h create mode 100644 include/hostservices.h create mode 100644 include/interrupts.h create mode 100644 include/io.h create mode 100644 include/lock.h create mode 100644 include/lpc.h create mode 100644 include/mem-map.h create mode 100644 include/mem_region-malloc.h create mode 100644 include/mem_region.h create mode 100644 include/memory.h create mode 100644 include/nx.h create mode 100644 include/op-panel.h create mode 100644 include/opal-internal.h create mode 100644 include/opal-msg.h create mode 100644 include/opal.h create mode 100644 include/p5ioc2-regs.h create mode 100644 include/p5ioc2.h create mode 100644 include/p7ioc-regs.h create mode 100644 include/p7ioc.h create mode 100644 include/pci-cfg.h create mode 100644 include/pci.h create mode 100644 include/phb3-regs.h create mode 100644 include/phb3.h create mode 100644 include/platform.h create mode 100644 include/processor.h create mode 100644 include/psi.h create mode 100644 include/sfc-ctrl.h create mode 100644 include/skiboot.h create mode 100644 include/spcn.h create mode 100644 include/stack.h create mode 100644 include/timebase.h create mode 100644 include/trace.h create mode 100644 include/trace_types.h create mode 100644 include/types.h create mode 100644 include/vpd.h create mode 100644 include/xscom.h (limited to 'include') 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 + +/* 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 +#include + +/* + * 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 + +/* 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 + +/* + * 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 +#include +#include +#include +#include + +/* + * 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 +#include + +/* 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 + +/* 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 + +#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 + +/* 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 +#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 +#include + +/* 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 + +/* 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 +#include + +/* + * 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 +#include +#include +#include + +/* + * 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 + +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 +#include + +/* 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 +#include + +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 + +/* 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 + +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 + +#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 +#include + +/* 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 + + +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include + +/* + * 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 +#include +#include + +#include + +/* + * 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 +#include +#include + +/* 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 + +/* + * 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 + +/* 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 +#include + +/* + * 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 + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* 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 + +/* 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 + +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 +#include +#include +#include + +#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 + +/* 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 +#include +#include + +/* + * 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 */ -- cgit v1.1