blob: db0c0867c3ff754e5572817c9a5985b2a4af55dc [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
/* 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 pau;
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;
};
struct ocapi_phy_setup {
int tx_ffe_pre_coeff;
int tx_ffe_post_coeff;
int tx_ffe_boost_en;
};
/* 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 */
uint8_t i2c_dev_addr; /* I2C device address */
uint8_t i2c_intreset_pin; /* I2C pin to write to reset */
uint8_t i2c_predetect_pin; /* I2C pin to read for presence */
int64_t (*i2c_assert_reset)(uint8_t i2c_bus_id);
int64_t (*i2c_deassert_reset)(uint8_t i2c_bus_id);
const char *(*ocapi_slot_label)(uint32_t chip_id, uint32_t brick_index);
const struct ocapi_phy_setup *phy_setup;
};
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);
/* PAU device detection */
void (*pau_device_detect)(struct pau *pau);
/*
* 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 for each device during pci_add_device_nodes() descend
* to create the device tree, in order to get the correct per-platform
* preference for the ibm,loc-code property
*/
void (*pci_add_loc_code)(struct dt_node *np,
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
* previous start_preload_resource call for this resource.
* If not implemented, will return true and start_preload_resource
* *must* have synchronously done the load.
* Returns 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 */