// SPDX-License-Identifier: Apache-2.0 /* Copyright 2013-2019 IBM Corp. */ #ifndef __PLATFORM_H #define __PLATFORM_H /* Some fwd declarations for types used further down */ struct phb; struct pci_device; struct pci_slot; struct errorlog; struct npu2; struct npu3; enum resource_id { RESOURCE_ID_KERNEL, RESOURCE_ID_INITRAMFS, RESOURCE_ID_CAPP, RESOURCE_ID_IMA_CATALOG, RESOURCE_ID_VERSION, RESOURCE_ID_KERNEL_FW, }; #define RESOURCE_SUBID_NONE 0 #define RESOURCE_SUBID_SUPPORTED 1 struct bmc_hw_config { uint32_t scu_revision_id; uint32_t mcr_configuration; uint32_t mcr_scu_mpll; uint32_t mcr_scu_strap; }; struct bmc_sw_config { /* * Map IPMI_OEM_X to vendor commands for this BMC * 0 = unimplimented */ uint32_t ipmi_oem_partial_add_esel; uint32_t ipmi_oem_pnor_access_status; uint32_t ipmi_oem_hiomap_cmd; }; struct bmc_platform { const char *name; const struct bmc_hw_config *hw; const struct bmc_sw_config *sw; }; /* OpenCAPI platform-specific I2C information */ struct platform_ocapi { uint8_t i2c_engine; /* I2C engine number */ uint8_t i2c_port; /* I2C port number */ uint8_t i2c_reset_addr; /* I2C address for reset */ uint8_t i2c_reset_brick2; /* I2C pin to write to reset brick 2 */ uint8_t i2c_reset_brick3; /* I2C pin to write to reset brick 3 */ uint8_t i2c_reset_brick4; /* I2C pin to write to reset brick 4 */ uint8_t i2c_reset_brick5; /* I2C pin to write to reset brick 5 */ uint8_t i2c_presence_addr; /* I2C address for presence detection */ uint8_t i2c_presence_brick2; /* I2C pin to read for presence on brick 2 */ uint8_t i2c_presence_brick3; /* I2C pin to read for presence on brick 3 */ uint8_t i2c_presence_brick4; /* I2C pin to read for presence on brick 4 */ uint8_t i2c_presence_brick5; /* I2C pin to read for presence on brick 5 */ bool odl_phy_swap; /* Swap ODL1 to use brick 2 rather than * brick 1 lanes */ }; struct dt_node; /* * Just for FSP platforms, allows us to partly decouple * FSP specific code from core code. */ struct platform_psi { void (*psihb_interrupt)(void); void (*link_established)(void); void (*fsp_interrupt)(void); }; /* * Some PRD functionality is platform specific. */ struct platform_prd { void (*msg_response)(uint32_t rc); int (*send_error_log)(uint32_t plid, uint32_t dsize, void *data); int (*send_hbrt_msg)(void *data, u64 dsize); int (*wakeup)(uint32_t i_core, uint32_t i_mode); int (*fsp_occ_load_start_status)(u64 chipid, s64 status); int (*fsp_occ_reset_status)(u64 chipid, s64 status); }; /* * Each platform can provide a set of hooks * that can affect the generic code */ struct platform { const char *name; /* * If BMC is constant, bmc platform specified here. * Platforms can also call set_bmc_platform() if BMC platform is * not a constant. */ const struct bmc_platform *bmc; /* * PSI handling code. FSP specific. */ const struct platform_psi *psi; /* * Platform specific PRD handling */ const struct platform_prd *prd; /* OpenCAPI platform-specific I2C information */ const struct platform_ocapi *ocapi; /* NPU device detection */ void (*npu2_device_detect)(struct npu2 *npu); void (*npu3_device_detect)(struct npu3 *npu); /* * 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); /* * Called once every thread is back in skiboot as part of fast reboot. */ void (*fast_reboot_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); /* * This is called before resetting the PHBs (lift PERST) and * probing the devices. The PHBs have already been initialized. */ void (*pre_pci_fixup)(void); /* * 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); int (*secvar_init)(void); /* * OCC timeout. This return how long we should wait for the OCC * before timing out. This lets us use a high value on larger FSP * machines and cut it off completely on BML boots and OpenPower * machines without pre-existing OCC firmware. Returns a value in * seconds. */ uint32_t (*occ_timeout)(void); int (*elog_commit)(struct errorlog *buf); /* * Initiate loading an external resource (e.g. kernel payload, OCC) * into a preallocated buffer. * This is designed to asynchronously load external resources. * Returns OPAL_SUCCESS or error. */ int (*start_preload_resource)(enum resource_id id, uint32_t idx, void *buf, size_t *len); /* * Returns true when resource is loaded. * Only has to return true once, for the * preivous start_preload_resource call for this resource. * If not implemented, will return true and start_preload_resource * *must* have synchronously done the load. * Retruns OPAL_SUCCESS, OPAL_BUSY or an error code */ int (*resource_loaded)(enum resource_id id, uint32_t idx); /* * Executed just prior to creating the dtb for the kernel. */ void (*finalise_dt)(bool is_reboot); /* * Executed just prior to handing control over to the payload. * Used to terminate watchdogs, etc. */ void (*exit)(void); /* * Read a sensor value */ int64_t (*sensor_read)(uint32_t sensor_hndl, int token, __be64 *sensor_data); /* * Return the heartbeat time */ int (*heartbeat_time)(void); /* * OPAL terminate */ void __attribute__((noreturn)) (*terminate)(const char *msg); /* * SEEPROM update routine */ void (*seeprom_update)(void); /* * Operator Panel display * Physical FSP op panel or LPC port 80h * or any other "get boot status out to the user" thing. */ void (*op_display)(enum op_severity sev, enum op_module mod, uint16_t code); /* * VPD load. * Currently FSP specific. */ void (*vpd_iohub_load)(struct dt_node *hub_node); }; extern struct platform __platforms_start; extern struct platform __platforms_end; extern struct platform platform; extern const struct bmc_platform *bmc_platform; extern bool manufacturing_mode; #define DECLARE_PLATFORM(name)\ static const struct platform __used __section(".platforms") name ##_platform extern void probe_platform(void); extern int start_preload_resource(enum resource_id id, uint32_t subid, void *buf, size_t *len); extern int resource_loaded(enum resource_id id, uint32_t idx); extern int wait_for_resource_loaded(enum resource_id id, uint32_t idx); extern void set_bmc_platform(const struct bmc_platform *bmc); #endif /* __PLATFORM_H */