diff options
Diffstat (limited to 'roms/skiboot/platforms/ibm-fsp/common.c')
-rw-r--r-- | roms/skiboot/platforms/ibm-fsp/common.c | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/roms/skiboot/platforms/ibm-fsp/common.c b/roms/skiboot/platforms/ibm-fsp/common.c new file mode 100644 index 000000000..4a723b25b --- /dev/null +++ b/roms/skiboot/platforms/ibm-fsp/common.c @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* Copyright 2013-2019 IBM Corp. */ + + +#include <skiboot.h> +#include <fsp.h> +#include <fsp-sysparam.h> +#include <opal.h> +#include <console.h> +#include <hostservices.h> +#include <ipmi.h> +#include <debug_descriptor.h> +#include <occ.h> + +#include "ibm-fsp.h" + +static void map_debug_areas(void) +{ + uint64_t t, i; + + /* Our memcons is in a section of its own and already + * aligned to 4K. The buffers are mapped as a whole + */ + fsp_tce_map(PSI_DMA_MEMCONS, &memcons, 0x1000); + fsp_tce_map(PSI_DMA_LOG_BUF, (void*)INMEM_CON_START, INMEM_CON_LEN); + + debug_descriptor.memcons_tce = cpu_to_be32(PSI_DMA_MEMCONS); + t = be64_to_cpu(memcons.obuf_phys) - INMEM_CON_START + PSI_DMA_LOG_BUF; + debug_descriptor.memcons_obuf_tce = cpu_to_be32(t); + t = be64_to_cpu(memcons.ibuf_phys) - INMEM_CON_START + PSI_DMA_LOG_BUF; + debug_descriptor.memcons_ibuf_tce = cpu_to_be32(t); + + t = PSI_DMA_TRACE_BASE; + for (i = 0; i < be32_to_cpu(debug_descriptor.num_traces); i++) { + /* + * Trace buffers are misaligned by 0x10 due to the lock + * in the trace structure, and their size is also not + * completely aligned. (They are allocated so that with + * the lock included, they do cover entire multiple of + * a 4K page however). + * + * This means we have to map the lock into the TCEs and + * align everything. Not a huge deal but needs to be + * taken into account. + * + * Note: Maybe we should map them read-only... + */ + uint64_t tstart, tend, toff, tsize; + uint64_t trace_phys = be64_to_cpu(debug_descriptor.trace_phys[i]); + uint32_t trace_size = be32_to_cpu(debug_descriptor.trace_size[i]); + + tstart = ALIGN_DOWN(trace_phys, 0x1000); + tend = ALIGN_UP(trace_phys + trace_size, 0x1000); + toff = trace_phys - tstart; + tsize = tend - tstart; + + fsp_tce_map(t, (void *)tstart, tsize); + debug_descriptor.trace_tce[i] = cpu_to_be32(t + toff); + t += tsize; + } +} + + +void ibm_fsp_init(void) +{ + /* Early initializations of the FSP interface */ + fsp_init(); + map_debug_areas(); + fsp_sysparam_init(); + + /* Get ready to receive E0 class messages. We need to respond + * to some of these for the init sequence to make forward progress + */ + fsp_console_preinit(); + + /* Get ready to receive OCC related messages */ + occ_fsp_init(); + + /* Get ready to receive Memory [Un]corretable Error messages. */ + fsp_memory_err_init(); + + /* Initialize elog access */ + fsp_elog_read_init(); + fsp_elog_write_init(); + + /* Initiate dump service */ + fsp_dump_init(); + + /* Start FSP/HV state controller & perform OPL */ + fsp_opl(); + + /* Preload hostservices lids */ + hservices_lid_preload(); + + /* Initialize SP attention area */ + fsp_attn_init(); + + /* Initialize monitoring of TOD topology change event notification */ + fsp_chiptod_init(); + + /* Send MDST table notification to FSP */ + op_display(OP_LOG, OP_MOD_INIT, 0x0000); + fsp_mdst_table_init(); + + /* Initialize the panel */ + op_display(OP_LOG, OP_MOD_INIT, 0x0001); + fsp_oppanel_init(); + + /* Start the surveillance process */ + op_display(OP_LOG, OP_MOD_INIT, 0x0002); + fsp_init_surveillance(); + + /* IPMI */ + fsp_ipmi_init(); + ipmi_opal_init(); + + /* Initialize sensor access */ + op_display(OP_LOG, OP_MOD_INIT, 0x0003); + fsp_init_sensor(); + + /* LED */ + op_display(OP_LOG, OP_MOD_INIT, 0x0004); + fsp_led_init(); + + /* Monitor for DIAG events */ + op_display(OP_LOG, OP_MOD_INIT, 0x0005); + fsp_init_diag(); + + /* Finish initializing the console */ + op_display(OP_LOG, OP_MOD_INIT, 0x0006); + fsp_console_init(); + + /* Read our initial RTC value */ + op_display(OP_LOG, OP_MOD_INIT, 0x0008); + fsp_rtc_init(); + + /* Initialize code update access */ + op_display(OP_LOG, OP_MOD_INIT, 0x0009); + fsp_code_update_init(); + + /* EPOW */ + op_display(OP_LOG, OP_MOD_INIT, 0x000A); + fsp_epow_init(); + + /* EPOW */ + op_display(OP_LOG, OP_MOD_INIT, 0x000B); + fsp_dpo_init(); + + /* Setup console */ + if (fsp_present()) + fsp_console_add_nodes(); + + if (proc_gen >= proc_gen_p9) + prd_init(); + + preload_io_vpd(); +} + +void ibm_fsp_finalise_dt(bool is_reboot) +{ + if (is_reboot) + return; + + /* + * LED related SPCN commands might take a while to + * complete. Call this as late as possible to + * ensure we have all the LED information. + */ + create_led_device_nodes(); + + /* + * OCC takes few secs to boot. Call this as late as + * as possible to avoid delay. + */ + occ_pstates_init(); + + /* Wait for FW VPD data read to complete */ + fsp_code_update_wait_vpd(true); + + fsp_console_select_stdout(); +} + +void ibm_fsp_exit(void) +{ + op_panel_disable_src_echo(); + + /* Clear SRCs on the op-panel when Linux starts */ + op_panel_clear_src(); +} + +int64_t ibm_fsp_cec_reboot(void) +{ + uint32_t cmd = FSP_CMD_REBOOT; + + if (!fsp_present()) + return OPAL_UNSUPPORTED; + + /* Flash new firmware */ + if (fsp_flash_term_hook && + fsp_flash_term_hook() == OPAL_SUCCESS) + cmd = FSP_CMD_DEEP_REBOOT; + + /* Clear flash hook */ + fsp_flash_term_hook = NULL; + + printf("FSP: Sending 0x%02x reboot command to FSP...\n", cmd); + + /* If that failed, talk to the FSP */ + if (fsp_sync_msg(fsp_mkmsg(cmd, 0), true)) + return OPAL_BUSY_EVENT; + + return OPAL_SUCCESS; +} + +int64_t ibm_fsp_cec_power_down(uint64_t request) +{ + /* Request is: + * + * 0 = normal + * 1 = immediate + * (we do not allow 2 for "pci cfg reset" just yet) + */ + + if (request !=0 && request != 1) + return OPAL_PARAMETER; + + if (!fsp_present()) + return OPAL_UNSUPPORTED; + + /* Flash new firmware */ + if (fsp_flash_term_hook) + fsp_flash_term_hook(); + + /* Clear flash hook */ + fsp_flash_term_hook = NULL; + + printf("FSP: Sending shutdown command to FSP...\n"); + + if (fsp_sync_msg(fsp_mkmsg(FSP_CMD_POWERDOWN_NORM, 1, request), true)) + return OPAL_BUSY_EVENT; + + fsp_reset_links(); + return OPAL_SUCCESS; +} + +int64_t ibm_fsp_sensor_read(uint32_t sensor_hndl, int token, + __be64 *sensor_data) +{ + return fsp_opal_read_sensor(sensor_hndl, token, sensor_data); +} + +int __attrconst fsp_heartbeat_time(void) +{ + /* Same as core/timer.c HEARTBEAT_DEFAULT_MS * 10 */ + return 200 * 10; +} + +static void fsp_psihb_interrupt(void) +{ + /* Poll the console buffers on any interrupt since we don't + * get send notifications + */ + fsp_console_poll(NULL); +} + +struct platform_psi fsp_platform_psi = { + .psihb_interrupt = fsp_psihb_interrupt, + .link_established = fsp_reinit_fsp, + .fsp_interrupt = fsp_interrupt, +}; + +struct platform_prd fsp_platform_prd = { + .msg_response = hservice_hbrt_msg_response, + .send_error_log = hservice_send_error_log, + .send_hbrt_msg = hservice_send_hbrt_msg, + .wakeup = hservice_wakeup, + .fsp_occ_load_start_status = fsp_occ_load_start_status, + .fsp_occ_reset_status = fsp_occ_reset_status, +}; |