aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/platforms/ibm-fsp/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/platforms/ibm-fsp/common.c')
-rw-r--r--roms/skiboot/platforms/ibm-fsp/common.c279
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,
+};