/*
 * This file is provided under a dual BSD/GPLv2 license.  When using or
 * redistributing this file, you may do so under either license.
 *
 * GPL LICENSE SUMMARY
 *
 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 * The full GNU General Public License is included in this distribution
 * in the file called LICENSE.GPL.
 */

/* probe_roms - scan for oem parameters */

#include <linux/kernel.h>
#include <linux/firmware.h>
#include <linux/uaccess.h>
#include <linux/efi.h>
#include <asm/probe_roms.h>

#include "isci.h"
#include "task.h"
#include "probe_roms.h"

static efi_char16_t isci_efivar_name[] = {
	'R', 's', 't', 'S', 'c', 'u', 'O'
};

struct isci_orom *isci_request_oprom(struct pci_dev *pdev)
{
	void __iomem *oprom = pci_map_biosrom(pdev);
	struct isci_orom *rom = NULL;
	size_t len, i;
	int j;
	char oem_sig[4];
	struct isci_oem_hdr oem_hdr;
	u8 *tmp, sum;

	if (!oprom)
		return NULL;

	len = pci_biosrom_size(pdev);
	rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL);
	if (!rom) {
		pci_unmap_biosrom(oprom);
		dev_warn(&pdev->dev,
			 "Unable to allocate memory for orom\n");
		return NULL;
	}

	for (i = 0; i < len && rom; i += ISCI_OEM_SIG_SIZE) {
		memcpy_fromio(oem_sig, oprom + i, ISCI_OEM_SIG_SIZE);

		/* we think we found the OEM table */
		if (memcmp(oem_sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) == 0) {
			size_t copy_len;

			memcpy_fromio(&oem_hdr, oprom + i, sizeof(oem_hdr));

			copy_len = min(oem_hdr.len - sizeof(oem_hdr),
				       sizeof(*rom));

			memcpy_fromio(rom,
				      oprom + i + sizeof(oem_hdr),
				      copy_len);

			/* calculate checksum */
			tmp = (u8 *)&oem_hdr;
			for (j = 0, sum = 0; j < sizeof(oem_hdr); j++, tmp++)
				sum += *tmp;

			tmp = (u8 *)rom;
			for (j = 0; j < sizeof(*rom); j++, tmp++)
				sum += *tmp;

			if (sum != 0) {
				dev_warn(&pdev->dev,
					 "OEM table checksum failed\n");
				continue;
			}

			/* keep going if that's not the oem param table */
			if (memcmp(rom->hdr.signature,
				   ISCI_ROM_SIG,
				   ISCI_ROM_SIG_SIZE) != 0)
				continue;

			dev_info(&pdev->dev,
				 "OEM parameter table found in OROM\n");
			break;
		}
	}

	if (i >= len) {
		dev_err(&pdev->dev, "oprom parse error\n");
		rom = NULL;
	}
	pci_unmap_biosrom(oprom);

	return rom;
}

struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw)
{
	struct isci_orom *orom = NULL, *data;
	int i, j;

	if (request_firmware(&fw, ISCI_FW_NAME, &pdev->dev) != 0)
		return NULL;

	if (fw->size < sizeof(*orom))
		goto out;

	data = (struct isci_orom *)fw->data;

	if (strncmp(ISCI_ROM_SIG, data->hdr.signature,
		    strlen(ISCI_ROM_SIG)) != 0)
		goto out;

	orom = devm_kzalloc(&pdev->dev, fw->size, GFP_KERNEL);
	if (!orom)
		goto out;

	memcpy(orom, fw->data, fw->size);

	if (is_c0(pdev) || is_c1(pdev))
		goto out;

	/*
	 * deprecated: override default amp_control for pre-preproduction
	 * silicon revisions
	 */
	for (i = 0; i < ARRAY_SIZE(orom->ctrl); i++)
		for (j = 0; j < ARRAY_SIZE(orom->ctrl[i].phys); j++) {
			orom->ctrl[i].phys[j].afe_tx_amp_control0 = 0xe7c03;
			orom->ctrl[i].phys[j].afe_tx_amp_control1 = 0xe7c03;
			orom->ctrl[i].phys[j].afe_tx_amp_control2 = 0xe7c03;
			orom->ctrl[i].phys[j].afe_tx_amp_control3 = 0xe7c03;
		}
 out:
	release_firmware(fw);

	return orom;
}

static struct efi *get_efi(void)
{
#ifdef CONFIG_EFI
	return &efi;
#else
	return NULL;
#endif
}

struct isci_orom *isci_get_efi_var(struct pci_dev *pdev)
{
	efi_status_t status;
	struct isci_orom *rom;
	struct isci_oem_hdr *oem_hdr;
	u8 *tmp, sum;
	int j;
	unsigned long data_len;
	u8 *efi_data;
	u32 efi_attrib = 0;

	data_len = 1024;
	efi_data = devm_kzalloc(&pdev->dev, data_len, GFP_KERNEL);
	if (!efi_data) {
		dev_warn(&pdev->dev,
			 "Unable to allocate memory for EFI data\n");
		return NULL;
	}

	rom = (struct isci_orom *)(efi_data + sizeof(struct isci_oem_hdr));

	if (get_efi())
		status = get_efi()->get_variable(isci_efivar_name,
						 &ISCI_EFI_VENDOR_GUID,
						 &efi_attrib,
						 &data_len,
						 efi_data);
	else
		status = EFI_NOT_FOUND;

	if (status != EFI_SUCCESS) {
		dev_warn(&pdev->dev,
			 "Unable to obtain EFI var data for OEM parms\n");
		return NULL;
	}

	oem_hdr = (struct isci_oem_hdr *)efi_data;

	if (memcmp(oem_hdr->sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) != 0) {
		dev_warn(&pdev->dev,
			 "Invalid OEM header signature\n");
		return NULL;
	}

	/* calculate checksum */
	tmp = (u8 *)efi_data;
	for (j = 0, sum = 0; j < (sizeof(*oem_hdr) + sizeof(*rom)); j++, tmp++)
		sum += *tmp;

	if (sum != 0) {
		dev_warn(&pdev->dev,
			 "OEM table checksum failed\n");
		return NULL;
	}

	if (memcmp(rom->hdr.signature,
		   ISCI_ROM_SIG,
		   ISCI_ROM_SIG_SIZE) != 0) {
		dev_warn(&pdev->dev,
			 "Invalid OEM table signature\n");
		return NULL;
	}

	return rom;
}
