/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2015-2016 Intel Corp.
 * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <arch/cpu.h>
#include <console/console.h>
#include <fsp/api.h>
#include <fsp/util.h>
#include <string.h>
#include <timestamp.h>

void fsp_notify(enum fsp_notify_phase phase)
{
	enum fsp_status ret;
	fsp_notify_fn fspnotify;
	struct fsp_notify_params notify_params = { .phase = phase };

	if (!fsps_hdr.notify_phase_entry_offset)
		die("Notify_phase_entry_offset is zero!\n");

	fspnotify = (void*) (fsps_hdr.image_base +
			    fsps_hdr.notify_phase_entry_offset);
	fsp_before_debug_notify(fspnotify, &notify_params);

	if (phase == AFTER_PCI_ENUM) {
		timestamp_add_now(TS_FSP_BEFORE_ENUMERATE);
		post_code(POST_FSP_NOTIFY_BEFORE_ENUMERATE);
	} else if (phase == READY_TO_BOOT) {
		timestamp_add_now(TS_FSP_BEFORE_FINALIZE);
		post_code(POST_FSP_NOTIFY_BEFORE_FINALIZE);
	}

	ret = fspnotify(&notify_params);

	if (phase == AFTER_PCI_ENUM) {
		timestamp_add_now(TS_FSP_AFTER_ENUMERATE);
		post_code(POST_FSP_NOTIFY_BEFORE_ENUMERATE);
	} else if (phase == READY_TO_BOOT) {
		timestamp_add_now(TS_FSP_AFTER_FINALIZE);
		post_code(POST_FSP_NOTIFY_BEFORE_FINALIZE);
	}
	fsp_debug_after_notify(ret);

	/* Handle any errors returned by FspNotify */
	fsp_handle_reset(ret);
	if (ret != FSP_SUCCESS) {
		printk(BIOS_SPEW, "FspNotify returned 0x%08x\n", ret);
		die("FspNotify returned an error!\n");
	}
}
