/*
 * Copyright 2019 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 */
#include <linux/pci.h>

#include "amdgpu.h"
#include "amdgpu_i2c.h"
#include "smu_v11_0_i2c.h"
#include "atom.h"
#include "amdgpu_fru_eeprom.h"

#define I2C_PRODUCT_INFO_ADDR		0xAC
#define I2C_PRODUCT_INFO_ADDR_SIZE	0x2
#define I2C_PRODUCT_INFO_OFFSET		0xC0

static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
{
	/* Only server cards have the FRU EEPROM
	 * TODO: See if we can figure this out dynamically instead of
	 * having to parse VBIOS versions.
	 */
	struct atom_context *atom_ctx = adev->mode_info.atom_context;

	/* VBIOS is of the format ###-DXXXYY-##. For SKU identification,
	 * we can use just the "DXXX" portion. If there were more models, we
	 * could convert the 3 characters to a hex integer and use a switch
	 * for ease/speed/readability. For now, 2 string comparisons are
	 * reasonable and not too expensive
	 */
	switch (adev->asic_type) {
	case CHIP_VEGA20:
		/* D161 and D163 are the VG20 server SKUs */
		if (strnstr(atom_ctx->vbios_version, "D161",
			    sizeof(atom_ctx->vbios_version)) ||
		    strnstr(atom_ctx->vbios_version, "D163",
			    sizeof(atom_ctx->vbios_version)))
			return true;
		else
			return false;
	default:
		return false;
	}
}

static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
			   unsigned char *buff)
{
	int ret, size;
	struct i2c_msg msg = {
			.addr   = I2C_PRODUCT_INFO_ADDR,
			.flags  = I2C_M_RD,
			.buf    = buff,
	};
	buff[0] = 0;
	buff[1] = addrptr;
	msg.len = I2C_PRODUCT_INFO_ADDR_SIZE + 1;
	ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1);

	if (ret < 1) {
		DRM_WARN("FRU: Failed to get size field");
		return ret;
	}

	/* The size returned by the i2c requires subtraction of 0xC0 since the
	 * size apparently always reports as 0xC0+actual size.
	 */
	size = buff[2] - I2C_PRODUCT_INFO_OFFSET;
	/* Add 1 since address field was 1 byte */
	buff[1] = addrptr + 1;

	msg.len = I2C_PRODUCT_INFO_ADDR_SIZE + size;
	ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1);

	if (ret < 1) {
		DRM_WARN("FRU: Failed to get data field");
		return ret;
	}

	return size;
}

int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
{
	unsigned char buff[34];
	int addrptr, size;
	int len;

	if (!is_fru_eeprom_supported(adev))
		return 0;

	/* If algo exists, it means that the i2c_adapter's initialized */
	if (!adev->pm.smu_i2c.algo) {
		DRM_WARN("Cannot access FRU, EEPROM accessor not initialized");
		return -ENODEV;
	}

	/* There's a lot of repetition here. This is due to the FRU having
	 * variable-length fields. To get the information, we have to find the
	 * size of each field, and then keep reading along and reading along
	 * until we get all of the data that we want. We use addrptr to track
	 * the address as we go
	 */

	/* The first fields are all of size 1-byte, from 0-7 are offsets that
	 * contain information that isn't useful to us.
	 * Bytes 8-a are all 1-byte and refer to the size of the entire struct,
	 * and the language field, so just start from 0xb, manufacturer size
	 */
	addrptr = 0xb;
	size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
	if (size < 1) {
		DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size);
		return -EINVAL;
	}

	/* Increment the addrptr by the size of the field, and 1 due to the
	 * size field being 1 byte. This pattern continues below.
	 */
	addrptr += size + 1;
	size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
	if (size < 1) {
		DRM_ERROR("Failed to read FRU product name, ret:%d", size);
		return -EINVAL;
	}

	len = size;
	/* Product name should only be 32 characters. Any more,
	 * and something could be wrong. Cap it at 32 to be safe
	 */
	if (len >= sizeof(adev->product_name)) {
		DRM_WARN("FRU Product Number is larger than 32 characters. This is likely a mistake");
		len = sizeof(adev->product_name) - 1;
	}
	/* Start at 2 due to buff using fields 0 and 1 for the address */
	memcpy(adev->product_name, &buff[2], len);
	adev->product_name[len] = '\0';

	addrptr += size + 1;
	size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
	if (size < 1) {
		DRM_ERROR("Failed to read FRU product number, ret:%d", size);
		return -EINVAL;
	}

	len = size;
	/* Product number should only be 16 characters. Any more,
	 * and something could be wrong. Cap it at 16 to be safe
	 */
	if (len >= sizeof(adev->product_number)) {
		DRM_WARN("FRU Product Number is larger than 16 characters. This is likely a mistake");
		len = sizeof(adev->product_number) - 1;
	}
	memcpy(adev->product_number, &buff[2], len);
	adev->product_number[len] = '\0';

	addrptr += size + 1;
	size = amdgpu_fru_read_eeprom(adev, addrptr, buff);

	if (size < 1) {
		DRM_ERROR("Failed to read FRU product version, ret:%d", size);
		return -EINVAL;
	}

	addrptr += size + 1;
	size = amdgpu_fru_read_eeprom(adev, addrptr, buff);

	if (size < 1) {
		DRM_ERROR("Failed to read FRU serial number, ret:%d", size);
		return -EINVAL;
	}

	len = size;
	/* Serial number should only be 16 characters. Any more,
	 * and something could be wrong. Cap it at 16 to be safe
	 */
	if (len >= sizeof(adev->serial)) {
		DRM_WARN("FRU Serial Number is larger than 16 characters. This is likely a mistake");
		len = sizeof(adev->serial) - 1;
	}
	memcpy(adev->serial, &buff[2], len);
	adev->serial[len] = '\0';

	return 0;
}
