From 1b07618e8a2d71308cf34950b98b70db02e64dea Mon Sep 17 00:00:00 2001 From: Stewart Smith Date: Tue, 18 Jun 2019 17:29:11 +1000 Subject: Split FSP OCC code out into hw/fsp/ Signed-off-by: Stewart Smith --- hw/fsp/Makefile.inc | 2 +- hw/fsp/fsp-occ.c | 424 ++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/occ.c | 388 +---------------------------------------------- 3 files changed, 426 insertions(+), 388 deletions(-) create mode 100644 hw/fsp/fsp-occ.c (limited to 'hw') diff --git a/hw/fsp/Makefile.inc b/hw/fsp/Makefile.inc index 7a477db..4649621 100644 --- a/hw/fsp/Makefile.inc +++ b/hw/fsp/Makefile.inc @@ -5,6 +5,6 @@ FSP_OBJS += fsp-surveillance.o fsp-codeupdate.o fsp-sensor.o FSP_OBJS += fsp-diag.o fsp-leds.o fsp-mem-err.o fsp-op-panel.o FSP_OBJS += fsp-elog-read.o fsp-elog-write.o fsp-epow.o fsp-dpo.o FSP_OBJS += fsp-dump.o fsp-mdst-table.o fsp-chiptod.o fsp-ipmi.o -FSP_OBJS += fsp-attn.o +FSP_OBJS += fsp-attn.o fsp-occ.o FSP = hw/fsp/built-in.a $(FSP): $(FSP_OBJS:%=hw/fsp/%) diff --git a/hw/fsp/fsp-occ.c b/hw/fsp/fsp-occ.c new file mode 100644 index 0000000..6286078 --- /dev/null +++ b/hw/fsp/fsp-occ.c @@ -0,0 +1,424 @@ +/* Copyright 2013-2019 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DEFINE_LOG_ENTRY(OPAL_RC_OCC_LOAD, OPAL_PLATFORM_ERR_EVT, OPAL_OCC, + OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL, + OPAL_NA); + +DEFINE_LOG_ENTRY(OPAL_RC_OCC_RESET, OPAL_PLATFORM_ERR_EVT, OPAL_OCC, + OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL, + OPAL_NA); + +struct occ_load_req { + u8 scope; + u32 dbob_id; + u32 seq_id; + struct list_node link; +}; +static LIST_HEAD(occ_load_req_list); + + +static void occ_queue_load(u8 scope, u32 dbob_id, u32 seq_id) +{ + struct occ_load_req *occ_req; + + occ_req = zalloc(sizeof(struct occ_load_req)); + if (!occ_req) { + /** + * @fwts-label OCCload_reqENOMEM + * @fwts-advice ENOMEM while allocating OCC load message. + * OCCs not started, consequently no power/frequency scaling + * will be functional. + */ + prlog(PR_ERR, "OCC: Could not allocate occ_load_req\n"); + return; + } + + occ_req->scope = scope; + occ_req->dbob_id = dbob_id; + occ_req->seq_id = seq_id; + list_add_tail(&occ_load_req_list, &occ_req->link); +} + +static void __occ_do_load(u8 scope, u32 dbob_id __unused, u32 seq_id) +{ + struct fsp_msg *stat; + int rc = -ENOMEM; + int status_word = 0; + struct proc_chip *chip = next_chip(NULL); + + /* Call HBRT... */ + rc = host_services_occ_load(); + + /* Handle fallback to preload */ + if (rc == -ENOENT && chip->homer_base) { + prlog(PR_INFO, "OCC: Load: Fallback to preloaded image\n"); + rc = 0; + } else if (!rc) { + struct opal_occ_msg occ_msg = { CPU_TO_BE64(OCC_LOAD), 0, 0 }; + + rc = _opal_queue_msg(OPAL_MSG_OCC, NULL, NULL, + sizeof(struct opal_occ_msg), &occ_msg); + if (rc) + prlog(PR_INFO, "OCC: Failed to queue message %d\n", + OCC_LOAD); + + /* Success, start OCC */ + rc = host_services_occ_start(); + } + if (rc) { + /* If either of hostservices call fail, send fail to FSP */ + /* Find a chip ID to send failure */ + for_each_chip(chip) { + if (scope == 0x01 && dbob_id != chip->dbob_id) + continue; + status_word = 0xB500 | (chip->pcid & 0xff); + break; + } + log_simple_error(&e_info(OPAL_RC_OCC_LOAD), + "OCC: Error %d in load/start OCC\n", rc); + } + + /* Send a single response for all chips */ + stat = fsp_mkmsg(FSP_CMD_LOAD_OCC_STAT, 2, status_word, seq_id); + if (stat) + rc = fsp_queue_msg(stat, fsp_freemsg); + if (rc) { + log_simple_error(&e_info(OPAL_RC_OCC_LOAD), + "OCC: Error %d queueing FSP OCC LOAD STATUS msg", rc); + fsp_freemsg(stat); + } +} + +void occ_poke_load_queue(void) +{ + struct occ_load_req *occ_req, *next; + + if (list_empty(&occ_load_req_list)) + return; + + list_for_each_safe(&occ_load_req_list, occ_req, next, link) { + __occ_do_load(occ_req->scope, occ_req->dbob_id, + occ_req->seq_id); + list_del(&occ_req->link); + free(occ_req); + } +} + +static u32 last_seq_id; +static bool in_ipl = true; +static void occ_do_load(u8 scope, u32 dbob_id __unused, u32 seq_id) +{ + struct fsp_msg *rsp; + int rc = -ENOMEM; + u8 err = 0; + + if (scope != 0x01 && scope != 0x02) { + /** + * @fwts-label OCCLoadInvalidScope + * @fwts-advice Invalid request for loading OCCs. Power and + * frequency management not functional + */ + prlog(PR_ERR, "OCC: Load message with invalid scope 0x%x\n", + scope); + err = 0x22; + } + + /* First queue up an OK response to the load message itself */ + rsp = fsp_mkmsg(FSP_RSP_LOAD_OCC | err, 0); + if (rsp) + rc = fsp_queue_msg(rsp, fsp_freemsg); + if (rc) { + log_simple_error(&e_info(OPAL_RC_OCC_LOAD), + "OCC: Error %d queueing FSP OCC LOAD reply\n", rc); + fsp_freemsg(rsp); + return; + } + + if (err) + return; + + if (proc_gen == proc_gen_p9) { + if (in_ipl) { + /* OCC is pre-loaded in P9, so send SUCCESS to FSP */ + rsp = fsp_mkmsg(FSP_CMD_LOAD_OCC_STAT, 2, 0, seq_id); + if (!rsp) + return; + + rc = fsp_queue_msg(rsp, fsp_freemsg); + if (rc) { + log_simple_error(&e_info(OPAL_RC_OCC_LOAD), + "OCC: Error %d queueing OCC LOAD STATUS msg", + rc); + fsp_freemsg(rsp); + } + in_ipl = false; + } else { + struct proc_chip *chip = next_chip(NULL); + + last_seq_id = seq_id; + prd_fsp_occ_load_start(chip->id); + } + return; + } + + /* + * Check if hostservices lid caching is complete. If not, queue + * the load request. + */ + if (!hservices_lid_preload_complete()) { + occ_queue_load(scope, dbob_id, seq_id); + return; + } + + __occ_do_load(scope, dbob_id, seq_id); +} + +int fsp_occ_reset_status(u64 chipid, s64 status) +{ + struct fsp_msg *stat; + int rc = OPAL_NO_MEM; + int status_word = 0; + + prlog(PR_INFO, "HBRT: OCC stop() completed with %lld\n", status); + + if (status) { + struct proc_chip *chip = get_chip(chipid); + + if (!chip) + return OPAL_PARAMETER; + + status_word = 0xfe00 | (chip->pcid & 0xff); + log_simple_error(&e_info(OPAL_RC_OCC_RESET), + "OCC: Error %lld in OCC reset of chip %lld\n", + status, chipid); + } else { + occ_msg_queue_occ_reset(); + } + + stat = fsp_mkmsg(FSP_CMD_RESET_OCC_STAT, 2, status_word, last_seq_id); + if (!stat) + return rc; + + rc = fsp_queue_msg(stat, fsp_freemsg); + if (rc) { + fsp_freemsg(stat); + log_simple_error(&e_info(OPAL_RC_OCC_RESET), + "OCC: Error %d queueing FSP OCC RESET STATUS message\n", + rc); + } + return rc; +} + +int fsp_occ_load_start_status(u64 chipid, s64 status) +{ + struct fsp_msg *stat; + int rc = OPAL_NO_MEM; + int status_word = 0; + + if (status) { + struct proc_chip *chip = get_chip(chipid); + + if (!chip) + return OPAL_PARAMETER; + + status_word = 0xB500 | (chip->pcid & 0xff); + log_simple_error(&e_info(OPAL_RC_OCC_LOAD), + "OCC: Error %d in load/start OCC %lld\n", rc, + chipid); + } + + stat = fsp_mkmsg(FSP_CMD_LOAD_OCC_STAT, 2, status_word, last_seq_id); + if (!stat) + return rc; + + rc = fsp_queue_msg(stat, fsp_freemsg); + if (rc) { + fsp_freemsg(stat); + log_simple_error(&e_info(OPAL_RC_OCC_LOAD), + "OCC: Error %d queueing FSP OCC LOAD STATUS msg", rc); + } + + return rc; +} + +static void occ_do_reset(u8 scope, u32 dbob_id, u32 seq_id) +{ + struct fsp_msg *rsp, *stat; + struct proc_chip *chip = next_chip(NULL); + int rc = -ENOMEM; + u8 err = 0; + + /* Check arguments */ + if (scope != 0x01 && scope != 0x02) { + /** + * @fwts-label OCCResetInvalidScope + * @fwts-advice Invalid request for resetting OCCs. Power and + * frequency management not functional + */ + prlog(PR_ERR, "OCC: Reset message with invalid scope 0x%x\n", + scope); + err = 0x22; + } + + /* First queue up an OK response to the reset message itself */ + rsp = fsp_mkmsg(FSP_RSP_RESET_OCC | err, 0); + if (rsp) + rc = fsp_queue_msg(rsp, fsp_freemsg); + if (rc) { + fsp_freemsg(rsp); + log_simple_error(&e_info(OPAL_RC_OCC_RESET), + "OCC: Error %d queueing FSP OCC RESET reply\n", rc); + return; + } + + /* If we had an error, return */ + if (err) + return; + + /* + * Call HBRT to stop OCC and leave it stopped. FSP will send load/start + * request subsequently. Also after few runtime restarts (currently 3), + * FSP will request OCC to left in stopped state. + */ + + switch (proc_gen) { + case proc_gen_p8: + rc = host_services_occ_stop(); + break; + case proc_gen_p9: + last_seq_id = seq_id; + chip = next_chip(NULL); + prd_fsp_occ_reset(chip->id); + return; + default: + return; + } + + /* Handle fallback to preload */ + if (rc == -ENOENT && chip->homer_base) { + prlog(PR_INFO, "OCC: Reset: Fallback to preloaded image\n"); + rc = 0; + } + if (!rc) { + /* Send a single success response for all chips */ + stat = fsp_mkmsg(FSP_CMD_RESET_OCC_STAT, 2, 0, seq_id); + if (stat) + rc = fsp_queue_msg(stat, fsp_freemsg); + if (rc) { + fsp_freemsg(stat); + log_simple_error(&e_info(OPAL_RC_OCC_RESET), + "OCC: Error %d queueing FSP OCC RESET" + " STATUS message\n", rc); + } + occ_msg_queue_occ_reset(); + } else { + + /* + * Then send a matching OCC Reset Status message with an 0xFE + * (fail) response code as well to the first matching chip + */ + for_each_chip(chip) { + if (scope == 0x01 && dbob_id != chip->dbob_id) + continue; + rc = -ENOMEM; + stat = fsp_mkmsg(FSP_CMD_RESET_OCC_STAT, 2, + 0xfe00 | (chip->pcid & 0xff), seq_id); + if (stat) + rc = fsp_queue_msg(stat, fsp_freemsg); + if (rc) { + fsp_freemsg(stat); + log_simple_error(&e_info(OPAL_RC_OCC_RESET), + "OCC: Error %d queueing FSP OCC RESET" + " STATUS message\n", rc); + } + break; + } + } +} + +static bool fsp_occ_msg(u32 cmd_sub_mod, struct fsp_msg *msg) +{ + u32 dbob_id, seq_id; + u8 scope; + + switch (cmd_sub_mod) { + case FSP_CMD_LOAD_OCC: + /* + * We get the "Load OCC" command at boot. We don't currently + * support loading it ourselves (we don't have the procedures, + * they will come with Host Services). For now HostBoot will + * have loaded a OCC firmware for us, but we still need to + * be nice and respond to OCC. + */ + scope = msg->data.bytes[3]; + dbob_id = msg->data.words[1]; + seq_id = msg->data.words[2]; + prlog(PR_INFO, "OCC: Got OCC Load message, scope=0x%x" + " dbob=0x%x seq=0x%x\n", scope, dbob_id, seq_id); + occ_do_load(scope, dbob_id, seq_id); + return true; + + case FSP_CMD_RESET_OCC: + /* + * We shouldn't be getting this one, but if we do, we have + * to reply something sensible or the FSP will get upset + */ + scope = msg->data.bytes[3]; + dbob_id = msg->data.words[1]; + seq_id = msg->data.words[2]; + prlog(PR_INFO, "OCC: Got OCC Reset message, scope=0x%x" + " dbob=0x%x seq=0x%x\n", scope, dbob_id, seq_id); + occ_do_reset(scope, dbob_id, seq_id); + return true; + } + return false; +} + +static struct fsp_client fsp_occ_client = { + .message = fsp_occ_msg, +}; + +void occ_fsp_init(void) +{ + /* OCC is supported in P8 and P9 */ + if (proc_gen < proc_gen_p8) + return; + + /* If we have an FSP, register for notifications */ + if (fsp_present()) + fsp_register_client(&fsp_occ_client, FSP_MCLASS_OCC); +} diff --git a/hw/occ.c b/hw/occ.c index 4e97839..161fe84 100644 --- a/hw/occ.c +++ b/hw/occ.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -33,6 +32,7 @@ #include #include #include +#include /* OCC Communication Area for PStates */ @@ -265,14 +265,6 @@ static bool occ_reset; static struct lock occ_lock = LOCK_UNLOCKED; static unsigned long homer_opal_data_offset; -DEFINE_LOG_ENTRY(OPAL_RC_OCC_LOAD, OPAL_PLATFORM_ERR_EVT, OPAL_OCC, - OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL, - OPAL_NA); - -DEFINE_LOG_ENTRY(OPAL_RC_OCC_RESET, OPAL_PLATFORM_ERR_EVT, OPAL_OCC, - OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL, - OPAL_NA); - DEFINE_LOG_ENTRY(OPAL_RC_OCC_PSTATE_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_OCC, OPAL_CEC_HARDWARE, OPAL_INFO, OPAL_NA); @@ -1849,14 +1841,6 @@ void occ_pstates_init(void) dt_add_property_cells(power_mgt, "domain-runs-at", domain_runs_at); } -struct occ_load_req { - u8 scope; - u32 dbob_id; - u32 seq_id; - struct list_node link; -}; -static LIST_HEAD(occ_load_req_list); - int find_master_and_slave_occ(uint64_t **master, uint64_t **slave, int *nr_masters, int *nr_slaves) { @@ -1901,161 +1885,6 @@ int find_master_and_slave_occ(uint64_t **master, uint64_t **slave, return 0; } -static void occ_queue_load(u8 scope, u32 dbob_id, u32 seq_id) -{ - struct occ_load_req *occ_req; - - occ_req = zalloc(sizeof(struct occ_load_req)); - if (!occ_req) { - /** - * @fwts-label OCCload_reqENOMEM - * @fwts-advice ENOMEM while allocating OCC load message. - * OCCs not started, consequently no power/frequency scaling - * will be functional. - */ - prlog(PR_ERR, "OCC: Could not allocate occ_load_req\n"); - return; - } - - occ_req->scope = scope; - occ_req->dbob_id = dbob_id; - occ_req->seq_id = seq_id; - list_add_tail(&occ_load_req_list, &occ_req->link); -} - -static void __occ_do_load(u8 scope, u32 dbob_id __unused, u32 seq_id) -{ - struct fsp_msg *stat; - int rc = -ENOMEM; - int status_word = 0; - struct proc_chip *chip = next_chip(NULL); - - /* Call HBRT... */ - rc = host_services_occ_load(); - - /* Handle fallback to preload */ - if (rc == -ENOENT && chip->homer_base) { - prlog(PR_INFO, "OCC: Load: Fallback to preloaded image\n"); - rc = 0; - } else if (!rc) { - struct opal_occ_msg occ_msg = { CPU_TO_BE64(OCC_LOAD), 0, 0 }; - - rc = _opal_queue_msg(OPAL_MSG_OCC, NULL, NULL, - sizeof(struct opal_occ_msg), &occ_msg); - if (rc) - prlog(PR_INFO, "OCC: Failed to queue message %d\n", - OCC_LOAD); - - /* Success, start OCC */ - rc = host_services_occ_start(); - } - if (rc) { - /* If either of hostservices call fail, send fail to FSP */ - /* Find a chip ID to send failure */ - for_each_chip(chip) { - if (scope == 0x01 && dbob_id != chip->dbob_id) - continue; - status_word = 0xB500 | (chip->pcid & 0xff); - break; - } - log_simple_error(&e_info(OPAL_RC_OCC_LOAD), - "OCC: Error %d in load/start OCC\n", rc); - } - - /* Send a single response for all chips */ - stat = fsp_mkmsg(FSP_CMD_LOAD_OCC_STAT, 2, status_word, seq_id); - if (stat) - rc = fsp_queue_msg(stat, fsp_freemsg); - if (rc) { - log_simple_error(&e_info(OPAL_RC_OCC_LOAD), - "OCC: Error %d queueing FSP OCC LOAD STATUS msg", rc); - fsp_freemsg(stat); - } -} - -void occ_poke_load_queue(void) -{ - struct occ_load_req *occ_req, *next; - - if (list_empty(&occ_load_req_list)) - return; - - list_for_each_safe(&occ_load_req_list, occ_req, next, link) { - __occ_do_load(occ_req->scope, occ_req->dbob_id, - occ_req->seq_id); - list_del(&occ_req->link); - free(occ_req); - } -} - -static u32 last_seq_id; -static bool in_ipl = true; -static void occ_do_load(u8 scope, u32 dbob_id __unused, u32 seq_id) -{ - struct fsp_msg *rsp; - int rc = -ENOMEM; - u8 err = 0; - - if (scope != 0x01 && scope != 0x02) { - /** - * @fwts-label OCCLoadInvalidScope - * @fwts-advice Invalid request for loading OCCs. Power and - * frequency management not functional - */ - prlog(PR_ERR, "OCC: Load message with invalid scope 0x%x\n", - scope); - err = 0x22; - } - - /* First queue up an OK response to the load message itself */ - rsp = fsp_mkmsg(FSP_RSP_LOAD_OCC | err, 0); - if (rsp) - rc = fsp_queue_msg(rsp, fsp_freemsg); - if (rc) { - log_simple_error(&e_info(OPAL_RC_OCC_LOAD), - "OCC: Error %d queueing FSP OCC LOAD reply\n", rc); - fsp_freemsg(rsp); - return; - } - - if (err) - return; - - if (proc_gen == proc_gen_p9) { - if (in_ipl) { - /* OCC is pre-loaded in P9, so send SUCCESS to FSP */ - rsp = fsp_mkmsg(FSP_CMD_LOAD_OCC_STAT, 2, 0, seq_id); - if (!rsp) - return; - - rc = fsp_queue_msg(rsp, fsp_freemsg); - if (rc) { - log_simple_error(&e_info(OPAL_RC_OCC_LOAD), - "OCC: Error %d queueing OCC LOAD STATUS msg", - rc); - fsp_freemsg(rsp); - } - in_ipl = false; - } else { - struct proc_chip *chip = next_chip(NULL); - - last_seq_id = seq_id; - prd_fsp_occ_load_start(chip->id); - } - return; - } - - /* - * Check if hostservices lid caching is complete. If not, queue - * the load request. - */ - if (!hservices_lid_preload_complete()) { - occ_queue_load(scope, dbob_id, seq_id); - return; - } - - __occ_do_load(scope, dbob_id, seq_id); -} int occ_msg_queue_occ_reset(void) { @@ -2089,169 +1918,6 @@ out: return rc; } -int fsp_occ_reset_status(u64 chipid, s64 status) -{ - struct fsp_msg *stat; - int rc = OPAL_NO_MEM; - int status_word = 0; - - prlog(PR_INFO, "HBRT: OCC stop() completed with %lld\n", status); - - if (status) { - struct proc_chip *chip = get_chip(chipid); - - if (!chip) - return OPAL_PARAMETER; - - status_word = 0xfe00 | (chip->pcid & 0xff); - log_simple_error(&e_info(OPAL_RC_OCC_RESET), - "OCC: Error %lld in OCC reset of chip %lld\n", - status, chipid); - } else { - occ_msg_queue_occ_reset(); - } - - stat = fsp_mkmsg(FSP_CMD_RESET_OCC_STAT, 2, status_word, last_seq_id); - if (!stat) - return rc; - - rc = fsp_queue_msg(stat, fsp_freemsg); - if (rc) { - fsp_freemsg(stat); - log_simple_error(&e_info(OPAL_RC_OCC_RESET), - "OCC: Error %d queueing FSP OCC RESET STATUS message\n", - rc); - } - return rc; -} - -int fsp_occ_load_start_status(u64 chipid, s64 status) -{ - struct fsp_msg *stat; - int rc = OPAL_NO_MEM; - int status_word = 0; - - if (status) { - struct proc_chip *chip = get_chip(chipid); - - if (!chip) - return OPAL_PARAMETER; - - status_word = 0xB500 | (chip->pcid & 0xff); - log_simple_error(&e_info(OPAL_RC_OCC_LOAD), - "OCC: Error %d in load/start OCC %lld\n", rc, - chipid); - } - - stat = fsp_mkmsg(FSP_CMD_LOAD_OCC_STAT, 2, status_word, last_seq_id); - if (!stat) - return rc; - - rc = fsp_queue_msg(stat, fsp_freemsg); - if (rc) { - fsp_freemsg(stat); - log_simple_error(&e_info(OPAL_RC_OCC_LOAD), - "OCC: Error %d queueing FSP OCC LOAD STATUS msg", rc); - } - - return rc; -} - -static void occ_do_reset(u8 scope, u32 dbob_id, u32 seq_id) -{ - struct fsp_msg *rsp, *stat; - struct proc_chip *chip = next_chip(NULL); - int rc = -ENOMEM; - u8 err = 0; - - /* Check arguments */ - if (scope != 0x01 && scope != 0x02) { - /** - * @fwts-label OCCResetInvalidScope - * @fwts-advice Invalid request for resetting OCCs. Power and - * frequency management not functional - */ - prlog(PR_ERR, "OCC: Reset message with invalid scope 0x%x\n", - scope); - err = 0x22; - } - - /* First queue up an OK response to the reset message itself */ - rsp = fsp_mkmsg(FSP_RSP_RESET_OCC | err, 0); - if (rsp) - rc = fsp_queue_msg(rsp, fsp_freemsg); - if (rc) { - fsp_freemsg(rsp); - log_simple_error(&e_info(OPAL_RC_OCC_RESET), - "OCC: Error %d queueing FSP OCC RESET reply\n", rc); - return; - } - - /* If we had an error, return */ - if (err) - return; - - /* - * Call HBRT to stop OCC and leave it stopped. FSP will send load/start - * request subsequently. Also after few runtime restarts (currently 3), - * FSP will request OCC to left in stopped state. - */ - - switch (proc_gen) { - case proc_gen_p8: - rc = host_services_occ_stop(); - break; - case proc_gen_p9: - last_seq_id = seq_id; - chip = next_chip(NULL); - prd_fsp_occ_reset(chip->id); - return; - default: - return; - } - - /* Handle fallback to preload */ - if (rc == -ENOENT && chip->homer_base) { - prlog(PR_INFO, "OCC: Reset: Fallback to preloaded image\n"); - rc = 0; - } - if (!rc) { - /* Send a single success response for all chips */ - stat = fsp_mkmsg(FSP_CMD_RESET_OCC_STAT, 2, 0, seq_id); - if (stat) - rc = fsp_queue_msg(stat, fsp_freemsg); - if (rc) { - fsp_freemsg(stat); - log_simple_error(&e_info(OPAL_RC_OCC_RESET), - "OCC: Error %d queueing FSP OCC RESET" - " STATUS message\n", rc); - } - occ_msg_queue_occ_reset(); - } else { - - /* - * Then send a matching OCC Reset Status message with an 0xFE - * (fail) response code as well to the first matching chip - */ - for_each_chip(chip) { - if (scope == 0x01 && dbob_id != chip->dbob_id) - continue; - rc = -ENOMEM; - stat = fsp_mkmsg(FSP_CMD_RESET_OCC_STAT, 2, - 0xfe00 | (chip->pcid & 0xff), seq_id); - if (stat) - rc = fsp_queue_msg(stat, fsp_freemsg); - if (rc) { - fsp_freemsg(stat); - log_simple_error(&e_info(OPAL_RC_OCC_RESET), - "OCC: Error %d queueing FSP OCC RESET" - " STATUS message\n", rc); - } - break; - } - } -} - #define PV_OCC_GP0 0x01000000 #define PV_OCC_GP0_AND 0x01000004 #define PV_OCC_GP0_OR 0x01000005 @@ -2280,47 +1946,6 @@ void occ_pnor_set_owner(enum pnor_owner owner) occ_pnor_set_one_owner(chip->id, owner); } -static bool fsp_occ_msg(u32 cmd_sub_mod, struct fsp_msg *msg) -{ - u32 dbob_id, seq_id; - u8 scope; - - switch (cmd_sub_mod) { - case FSP_CMD_LOAD_OCC: - /* - * We get the "Load OCC" command at boot. We don't currently - * support loading it ourselves (we don't have the procedures, - * they will come with Host Services). For now HostBoot will - * have loaded a OCC firmware for us, but we still need to - * be nice and respond to OCC. - */ - scope = msg->data.bytes[3]; - dbob_id = msg->data.words[1]; - seq_id = msg->data.words[2]; - prlog(PR_INFO, "OCC: Got OCC Load message, scope=0x%x" - " dbob=0x%x seq=0x%x\n", scope, dbob_id, seq_id); - occ_do_load(scope, dbob_id, seq_id); - return true; - - case FSP_CMD_RESET_OCC: - /* - * We shouldn't be getting this one, but if we do, we have - * to reply something sensible or the FSP will get upset - */ - scope = msg->data.bytes[3]; - dbob_id = msg->data.words[1]; - seq_id = msg->data.words[2]; - prlog(PR_INFO, "OCC: Got OCC Reset message, scope=0x%x" - " dbob=0x%x seq=0x%x\n", scope, dbob_id, seq_id); - occ_do_reset(scope, dbob_id, seq_id); - return true; - } - return false; -} - -static struct fsp_client fsp_occ_client = { - .message = fsp_occ_msg, -}; #define P8_OCB_OCI_OCCMISC 0x6a020 #define P8_OCB_OCI_OCCMISC_AND 0x6a021 @@ -2454,14 +2079,3 @@ void occ_p9_interrupt(uint32_t chip_id) xscom_write(chip_id, P9_OCB_OCI_OCCMISC_OR, OCB_OCI_OCIMISC_IRQ); } - -void occ_fsp_init(void) -{ - /* OCC is supported in P8 and P9 */ - if (proc_gen < proc_gen_p8) - return; - - /* If we have an FSP, register for notifications */ - if (fsp_present()) - fsp_register_client(&fsp_occ_client, FSP_MCLASS_OCC); -} -- cgit v1.1