/* Copyright 2013-2017 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 <skiboot.h>
#include <io.h>
#include <opal.h>
#include <chip.h>
#include <xscom.h>
#include <capp.h>

#define PHBERR(opal_id, chip_id, index, fmt, a...) \
	       prlog(PR_ERR, "PHB#%04x[%d:%d]: " fmt, \
		     opal_id, chip_id, \
		     index,  ## a)

static struct {
	uint32_t			ec_level;
	struct capp_lid_hdr		*lid;
	size_t size;
	int load_result;
} capp_ucode_info = { 0, NULL, 0, false };

#define CAPP_UCODE_MAX_SIZE 0x20000

struct lock capi_lock = LOCK_UNLOCKED;
struct capp_ops capi_ops = { NULL };

bool capp_ucode_loaded(struct proc_chip *chip, unsigned int index)
{
	return (chip->capp_ucode_loaded & (1 << index));
}

int preload_capp_ucode(void)
{
	struct dt_node *p;
	struct proc_chip *chip;
	uint32_t index;
	uint64_t rc;
	int ret;

	p = dt_find_compatible_node(dt_root, NULL, "ibm,power8-pbcq");

	if (!p) {
		p = dt_find_compatible_node(dt_root, NULL, "ibm,power9-pbcq");
		if (!p) {
			prlog(PR_INFO, "CAPI: WARNING: no compat thing found\n");
			return OPAL_SUCCESS;
		}
	}

	chip = get_chip(dt_get_chip_id(p));

	rc = xscom_read_cfam_chipid(chip->id, &index);
	if (rc) {
		prerror("CAPP: Error reading cfam chip-id\n");
		ret = OPAL_HARDWARE;
		return ret;
	}
	/* Keep ChipID and Major/Minor EC.  Mask out the Location Code. */
	index = index & 0xf0fff;

	/* Assert that we're preloading */
	assert(capp_ucode_info.lid == NULL);
	capp_ucode_info.load_result = OPAL_EMPTY;

	capp_ucode_info.ec_level = index;

	/* Is the ucode preloaded like for BML? */
	if (dt_has_node_property(p, "ibm,capp-ucode", NULL)) {
		capp_ucode_info.lid = (struct capp_lid_hdr *)(u64)
			dt_prop_get_u32(p, "ibm,capp-ucode");
		capp_ucode_info.load_result = OPAL_SUCCESS;
		ret = OPAL_SUCCESS;
		goto end;
	}
	/* If we successfully download the ucode, we leave it around forever */
	capp_ucode_info.size = CAPP_UCODE_MAX_SIZE;
	capp_ucode_info.lid = malloc(CAPP_UCODE_MAX_SIZE);
	if (!capp_ucode_info.lid) {
		prerror("CAPP: Can't allocate space for ucode lid\n");
		ret = OPAL_NO_MEM;
		goto end;
	}

	prlog(PR_INFO, "CAPI: Preloading ucode %x\n", capp_ucode_info.ec_level);

	ret = start_preload_resource(RESOURCE_ID_CAPP, index,
				     capp_ucode_info.lid,
				     &capp_ucode_info.size);

	if (ret != OPAL_SUCCESS) {
		prerror("CAPI: Failed to preload resource %d\n", ret);
		capp_ucode_info.load_result = ret;
	}

end:
	return ret;
}

static int64_t capp_lid_download(void)
{
	int64_t ret;

	if (capp_ucode_info.load_result != OPAL_EMPTY)
		return capp_ucode_info.load_result;

	capp_ucode_info.load_result = wait_for_resource_loaded(
		RESOURCE_ID_CAPP,
		capp_ucode_info.ec_level);

	if (capp_ucode_info.load_result != OPAL_SUCCESS) {
		prerror("CAPP: Error loading ucode lid. index=%x\n",
			capp_ucode_info.ec_level);
		ret = OPAL_RESOURCE;
		free(capp_ucode_info.lid);
		capp_ucode_info.lid = NULL;
		goto end;
	}

	ret = OPAL_SUCCESS;
end:
	return ret;
}

int64_t capp_load_ucode(unsigned int chip_id, uint32_t opal_id,
			unsigned int index, u64 lid_eyecatcher,
			uint32_t reg_offset,
			uint64_t apc_master_addr, uint64_t apc_master_write,
			uint64_t snp_array_addr, uint64_t snp_array_write)
{
	struct proc_chip *chip = get_chip(chip_id);
	struct capp_ucode_lid *ucode;
	struct capp_ucode_data *data;
	struct capp_lid_hdr *lid;
	uint64_t rc, val, addr;
	uint32_t chunk_count, offset;
	int i;

	if (capp_ucode_loaded(chip, index))
		return OPAL_SUCCESS;

	rc = capp_lid_download();
	if (rc)
		return rc;

	prlog(PR_INFO, "CHIP%i: CAPP ucode lid loaded at %p\n",
	      chip_id, capp_ucode_info.lid);

	lid = capp_ucode_info.lid;
	/*
	 * If lid header is present (on FSP machines), it'll tell us where to
	 * find the ucode.  Otherwise this is the ucode.
	 */
	ucode = (struct capp_ucode_lid *)lid;
	if (be64_to_cpu(lid->eyecatcher) == lid_eyecatcher) {
		if (be64_to_cpu(lid->version) != 0x1) {
			PHBERR(opal_id, chip_id, index,
			       "capi ucode lid header invalid\n");
			return OPAL_HARDWARE;
		}
		ucode = (struct capp_ucode_lid *)
			((char *)ucode + be64_to_cpu(lid->ucode_offset));
	}

	/* 'CAPPULID' in ASCII */
	if ((be64_to_cpu(ucode->eyecatcher) != 0x43415050554C4944) ||
	    (be64_to_cpu(ucode->version != 1))) {
		PHBERR(opal_id, chip_id, index,
		       "CAPP: ucode header invalid\n");
		return OPAL_HARDWARE;
	}

	offset = 0;
	while (offset < be64_to_cpu(ucode->data_size)) {
		data = (struct capp_ucode_data *)
			((char *)&ucode->data + offset);
		chunk_count = be32_to_cpu(data->hdr.chunk_count);
		offset += sizeof(struct capp_ucode_data_hdr) + chunk_count * 8;

		/* 'CAPPUCOD' in ASCII */
		if (be64_to_cpu(data->hdr.eyecatcher) != 0x4341505055434F44) {
			PHBERR(opal_id, chip_id, index,
			       "CAPP: ucode data header invalid:%i\n",
			       offset);
			return OPAL_HARDWARE;
		}

		switch (data->hdr.reg) {
		case apc_master_cresp:
			xscom_write(chip_id, apc_master_addr + reg_offset,
				    0);
			addr = apc_master_write;
			break;
		case apc_master_uop_table:
			xscom_write(chip_id, apc_master_addr + reg_offset,
				    0x180ULL << 52);
			addr = apc_master_write;
			break;
		case snp_ttype:
			xscom_write(chip_id, snp_array_addr + reg_offset,
				    0x5000ULL << 48);
			addr = snp_array_write;
			break;
		case snp_uop_table:
			xscom_write(chip_id, snp_array_addr + reg_offset,
				    0x4000ULL << 48);
			addr = snp_array_write;
			break;
		default:
			continue;
		}

		for (i = 0; i < chunk_count; i++) {
			val = be64_to_cpu(data->data[i]);
			xscom_write(chip_id, addr + reg_offset, val);
		}
	}

	chip->capp_ucode_loaded |= (1 << index);

	return OPAL_SUCCESS;
}

int64_t capp_get_info(int chip_id, struct phb *phb, struct capp_info *info)
{
	if (capi_ops.get_capp_info)
		return capi_ops.get_capp_info(chip_id, phb, info);

	return OPAL_PARAMETER;
}
