// SPDX-License-Identifier: GPL-2.0
/*
 * NVM helpers
 *
 * Copyright (C) 2020, Intel Corporation
 * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
 */

#include <linux/idr.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>

#include "tb.h"

#define NVM_MIN_SIZE		SZ_32K
#define NVM_MAX_SIZE		SZ_1M
#define NVM_DATA_DWORDS		16

/* Intel specific NVM offsets */
#define INTEL_NVM_DEVID			0x05
#define INTEL_NVM_VERSION		0x08
#define INTEL_NVM_CSS			0x10
#define INTEL_NVM_FLASH_SIZE		0x45

/* ASMedia specific NVM offsets */
#define ASMEDIA_NVM_DATE		0x1c
#define ASMEDIA_NVM_VERSION		0x28

static DEFINE_IDA(nvm_ida);

/**
 * struct tb_nvm_vendor_ops - Vendor specific NVM operations
 * @read_version: Reads out NVM version from the flash
 * @validate: Validates the NVM image before update (optional)
 * @write_headers: Writes headers before the rest of the image (optional)
 */
struct tb_nvm_vendor_ops {
	int (*read_version)(struct tb_nvm *nvm);
	int (*validate)(struct tb_nvm *nvm);
	int (*write_headers)(struct tb_nvm *nvm);
};

/**
 * struct tb_nvm_vendor - Vendor to &struct tb_nvm_vendor_ops mapping
 * @vendor: Vendor ID
 * @vops: Vendor specific NVM operations
 *
 * Maps vendor ID to NVM vendor operations. If there is no mapping then
 * NVM firmware upgrade is disabled for the device.
 */
struct tb_nvm_vendor {
	u16 vendor;
	const struct tb_nvm_vendor_ops *vops;
};

static int intel_switch_nvm_version(struct tb_nvm *nvm)
{
	struct tb_switch *sw = tb_to_switch(nvm->dev);
	u32 val, nvm_size, hdr_size;
	int ret;

	/*
	 * If the switch is in safe-mode the only accessible portion of
	 * the NVM is the non-active one where userspace is expected to
	 * write new functional NVM.
	 */
	if (sw->safe_mode)
		return 0;

	ret = tb_switch_nvm_read(sw, INTEL_NVM_FLASH_SIZE, &val, sizeof(val));
	if (ret)
		return ret;

	hdr_size = sw->generation < 3 ? SZ_8K : SZ_16K;
	nvm_size = (SZ_1M << (val & 7)) / 8;
	nvm_size = (nvm_size - hdr_size) / 2;

	ret = tb_switch_nvm_read(sw, INTEL_NVM_VERSION, &val, sizeof(val));
	if (ret)
		return ret;

	nvm->major = (val >> 16) & 0xff;
	nvm->minor = (val >> 8) & 0xff;
	nvm->active_size = nvm_size;

	return 0;
}

static int intel_switch_nvm_validate(struct tb_nvm *nvm)
{
	struct tb_switch *sw = tb_to_switch(nvm->dev);
	unsigned int image_size, hdr_size;
	u16 ds_size, device_id;
	u8 *buf = nvm->buf;

	image_size = nvm->buf_data_size;

	/*
	 * FARB pointer must point inside the image and must at least
	 * contain parts of the digital section we will be reading here.
	 */
	hdr_size = (*(u32 *)buf) & 0xffffff;
	if (hdr_size + INTEL_NVM_DEVID + 2 >= image_size)
		return -EINVAL;

	/* Digital section start should be aligned to 4k page */
	if (!IS_ALIGNED(hdr_size, SZ_4K))
		return -EINVAL;

	/*
	 * Read digital section size and check that it also fits inside
	 * the image.
	 */
	ds_size = *(u16 *)(buf + hdr_size);
	if (ds_size >= image_size)
		return -EINVAL;

	if (sw->safe_mode)
		return 0;

	/*
	 * Make sure the device ID in the image matches the one
	 * we read from the switch config space.
	 */
	device_id = *(u16 *)(buf + hdr_size + INTEL_NVM_DEVID);
	if (device_id != sw->config.device_id)
		return -EINVAL;

	/* Skip headers in the image */
	nvm->buf_data_start = buf + hdr_size;
	nvm->buf_data_size = image_size - hdr_size;

	return 0;
}

static int intel_switch_nvm_write_headers(struct tb_nvm *nvm)
{
	struct tb_switch *sw = tb_to_switch(nvm->dev);

	if (sw->generation < 3) {
		int ret;

		/* Write CSS headers first */
		ret = dma_port_flash_write(sw->dma_port,
			DMA_PORT_CSS_ADDRESS, nvm->buf + INTEL_NVM_CSS,
			DMA_PORT_CSS_MAX_SIZE);
		if (ret)
			return ret;
	}

	return 0;
}

static const struct tb_nvm_vendor_ops intel_switch_nvm_ops = {
	.read_version = intel_switch_nvm_version,
	.validate = intel_switch_nvm_validate,
	.write_headers = intel_switch_nvm_write_headers,
};

static int asmedia_switch_nvm_version(struct tb_nvm *nvm)
{
	struct tb_switch *sw = tb_to_switch(nvm->dev);
	u32 val;
	int ret;

	ret = tb_switch_nvm_read(sw, ASMEDIA_NVM_VERSION, &val, sizeof(val));
	if (ret)
		return ret;

	nvm->major = (val << 16) & 0xff0000;
	nvm->major |= val & 0x00ff00;
	nvm->major |= (val >> 16) & 0x0000ff;

	ret = tb_switch_nvm_read(sw, ASMEDIA_NVM_DATE, &val, sizeof(val));
	if (ret)
		return ret;

	nvm->minor = (val << 16) & 0xff0000;
	nvm->minor |= val & 0x00ff00;
	nvm->minor |= (val >> 16) & 0x0000ff;

	/* ASMedia NVM size is fixed to 512k */
	nvm->active_size = SZ_512K;

	return 0;
}

static const struct tb_nvm_vendor_ops asmedia_switch_nvm_ops = {
	.read_version = asmedia_switch_nvm_version,
};

/* Router vendor NVM support table */
static const struct tb_nvm_vendor switch_nvm_vendors[] = {
	{ 0x174c, &asmedia_switch_nvm_ops },
	{ PCI_VENDOR_ID_INTEL, &intel_switch_nvm_ops },
	{ 0x8087, &intel_switch_nvm_ops },
};

static int intel_retimer_nvm_version(struct tb_nvm *nvm)
{
	struct tb_retimer *rt = tb_to_retimer(nvm->dev);
	u32 val, nvm_size;
	int ret;

	ret = tb_retimer_nvm_read(rt, INTEL_NVM_VERSION, &val, sizeof(val));
	if (ret)
		return ret;

	nvm->major = (val >> 16) & 0xff;
	nvm->minor = (val >> 8) & 0xff;

	ret = tb_retimer_nvm_read(rt, INTEL_NVM_FLASH_SIZE, &val, sizeof(val));
	if (ret)
		return ret;

	nvm_size = (SZ_1M << (val & 7)) / 8;
	nvm_size = (nvm_size - SZ_16K) / 2;
	nvm->active_size = nvm_size;

	return 0;
}

static int intel_retimer_nvm_validate(struct tb_nvm *nvm)
{
	struct tb_retimer *rt = tb_to_retimer(nvm->dev);
	unsigned int image_size, hdr_size;
	u8 *buf = nvm->buf;
	u16 ds_size, device;

	image_size = nvm->buf_data_size;

	/*
	 * FARB pointer must point inside the image and must at least
	 * contain parts of the digital section we will be reading here.
	 */
	hdr_size = (*(u32 *)buf) & 0xffffff;
	if (hdr_size + INTEL_NVM_DEVID + 2 >= image_size)
		return -EINVAL;

	/* Digital section start should be aligned to 4k page */
	if (!IS_ALIGNED(hdr_size, SZ_4K))
		return -EINVAL;

	/*
	 * Read digital section size and check that it also fits inside
	 * the image.
	 */
	ds_size = *(u16 *)(buf + hdr_size);
	if (ds_size >= image_size)
		return -EINVAL;

	/*
	 * Make sure the device ID in the image matches the retimer
	 * hardware.
	 */
	device = *(u16 *)(buf + hdr_size + INTEL_NVM_DEVID);
	if (device != rt->device)
		return -EINVAL;

	/* Skip headers in the image */
	nvm->buf_data_start = buf + hdr_size;
	nvm->buf_data_size = image_size - hdr_size;

	return 0;
}

static const struct tb_nvm_vendor_ops intel_retimer_nvm_ops = {
	.read_version = intel_retimer_nvm_version,
	.validate = intel_retimer_nvm_validate,
};

/* Retimer vendor NVM support table */
static const struct tb_nvm_vendor retimer_nvm_vendors[] = {
	{ 0x8087, &intel_retimer_nvm_ops },
};

/**
 * tb_nvm_alloc() - Allocate new NVM structure
 * @dev: Device owning the NVM
 *
 * Allocates new NVM structure with unique @id and returns it.
 *
 * Return:
 * * Pointer to &struct tb_nvm - On success.
 * * %-EOPNOTSUPP - If the NVM format of the @dev is not known by the
 *   kernel.
 * * %ERR_PTR - In case of failure.
 */
struct tb_nvm *tb_nvm_alloc(struct device *dev)
{
	const struct tb_nvm_vendor_ops *vops = NULL;
	struct tb_nvm *nvm;
	int ret, i;

	if (tb_is_switch(dev)) {
		const struct tb_switch *sw = tb_to_switch(dev);

		for (i = 0; i < ARRAY_SIZE(switch_nvm_vendors); i++) {
			const struct tb_nvm_vendor *v = &switch_nvm_vendors[i];

			if (v->vendor == sw->config.vendor_id) {
				vops = v->vops;
				break;
			}
		}

		if (!vops) {
			tb_sw_dbg(sw, "router NVM format of vendor %#x unknown\n",
				  sw->config.vendor_id);
			return ERR_PTR(-EOPNOTSUPP);
		}
	} else if (tb_is_retimer(dev)) {
		const struct tb_retimer *rt = tb_to_retimer(dev);

		for (i = 0; i < ARRAY_SIZE(retimer_nvm_vendors); i++) {
			const struct tb_nvm_vendor *v = &retimer_nvm_vendors[i];

			if (v->vendor == rt->vendor) {
				vops = v->vops;
				break;
			}
		}

		if (!vops) {
			dev_dbg(dev, "retimer NVM format of vendor %#x unknown\n",
				rt->vendor);
			return ERR_PTR(-EOPNOTSUPP);
		}
	} else {
		return ERR_PTR(-EOPNOTSUPP);
	}

	nvm = kzalloc_obj(*nvm);
	if (!nvm)
		return ERR_PTR(-ENOMEM);

	ret = ida_alloc(&nvm_ida, GFP_KERNEL);
	if (ret < 0) {
		kfree(nvm);
		return ERR_PTR(ret);
	}

	nvm->id = ret;
	nvm->dev = dev;
	nvm->vops = vops;

	return nvm;
}

/**
 * tb_nvm_read_version() - Read and populate NVM version
 * @nvm: NVM structure
 *
 * Uses vendor specific means to read and fill out the existing
 * active NVM version.
 *
 * Return: %0 on success, negative errno otherwise.
 */
int tb_nvm_read_version(struct tb_nvm *nvm)
{
	const struct tb_nvm_vendor_ops *vops = nvm->vops;

	if (vops && vops->read_version)
		return vops->read_version(nvm);

	return -EOPNOTSUPP;
}

/**
 * tb_nvm_validate() - Validate new NVM image
 * @nvm: NVM structure
 *
 * Runs vendor specific validation over the new NVM image. As a
 * side effect, updates @nvm->buf_data_start and @nvm->buf_data_size
 * fields to match the actual data to be written to the NVM.
 *
 * Return: %0 on successful validation, negative errno otherwise.
 */
int tb_nvm_validate(struct tb_nvm *nvm)
{
	const struct tb_nvm_vendor_ops *vops = nvm->vops;
	unsigned int image_size;
	u8 *buf = nvm->buf;

	if (!buf)
		return -EINVAL;
	if (!vops)
		return -EOPNOTSUPP;

	/* Just do basic image size checks */
	image_size = nvm->buf_data_size;
	if (image_size < NVM_MIN_SIZE || image_size > NVM_MAX_SIZE)
		return -EINVAL;

	/*
	 * Set the default data start in the buffer. The validate method
	 * below can change this if needed.
	 */
	nvm->buf_data_start = buf;

	return vops->validate ? vops->validate(nvm) : 0;
}

/**
 * tb_nvm_write_headers() - Write headers before the rest of the image
 * @nvm: NVM structure
 *
 * If the vendor NVM format requires writing headers before the rest of
 * the image, this function does that. Can be called even if the device
 * does not need this.
 *
 * Return: %0 on success, negative errno otherwise.
 */
int tb_nvm_write_headers(struct tb_nvm *nvm)
{
	const struct tb_nvm_vendor_ops *vops = nvm->vops;

	return vops->write_headers ? vops->write_headers(nvm) : 0;
}

/**
 * tb_nvm_add_active() - Adds active NVMem device to NVM
 * @nvm: NVM structure
 * @reg_read: Pointer to the function to read the NVM (passed directly to the
 *	      NVMem device)
 *
 * Registers new active NVmem device for @nvm. The @reg_read is called
 * directly from NVMem so it must handle possible concurrent access if
 * needed. The first parameter passed to @reg_read is @nvm structure.
 *
 * Return: %0 on success, negative errno otherwise.
 */
int tb_nvm_add_active(struct tb_nvm *nvm, nvmem_reg_read_t reg_read)
{
	struct nvmem_config config;
	struct nvmem_device *nvmem;

	memset(&config, 0, sizeof(config));

	config.name = "nvm_active";
	config.reg_read = reg_read;
	config.read_only = true;
	config.id = nvm->id;
	config.stride = 4;
	config.word_size = 4;
	config.size = nvm->active_size;
	config.dev = nvm->dev;
	config.owner = THIS_MODULE;
	config.priv = nvm;

	nvmem = nvmem_register(&config);
	if (IS_ERR(nvmem))
		return PTR_ERR(nvmem);

	nvm->active = nvmem;
	return 0;
}

/**
 * tb_nvm_write_buf() - Write data to @nvm buffer
 * @nvm: NVM structure
 * @offset: Offset where to write the data
 * @val: Data buffer to write
 * @bytes: Number of bytes to write
 *
 * Helper function to cache the new NVM image before it is actually
 * written to the flash. Copies @bytes from @val to @nvm->buf starting
 * from @offset.
 *
 * Return:
 * * %0 - On success.
 * * %-ENOMEM - If buffer allocation failed.
 * * Negative errno - Another error occurred.
 */
int tb_nvm_write_buf(struct tb_nvm *nvm, unsigned int offset, void *val,
		     size_t bytes)
{
	if (!nvm->buf) {
		nvm->buf = vmalloc(NVM_MAX_SIZE);
		if (!nvm->buf)
			return -ENOMEM;
	}

	nvm->flushed = false;
	nvm->buf_data_size = offset + bytes;
	memcpy(nvm->buf + offset, val, bytes);
	return 0;
}

/**
 * tb_nvm_add_non_active() - Adds non-active NVMem device to NVM
 * @nvm: NVM structure
 * @reg_write: Pointer to the function to write the NVM (passed directly
 *	       to the NVMem device)
 *
 * Registers new non-active NVmem device for @nvm. The @reg_write is called
 * directly from NVMem so it must handle possible concurrent access if
 * needed. The first parameter passed to @reg_write is @nvm structure.
 * The size of the NVMem device is set to %NVM_MAX_SIZE.
 *
 * Return: %0 on success, negative errno otherwise.
 */
int tb_nvm_add_non_active(struct tb_nvm *nvm, nvmem_reg_write_t reg_write)
{
	struct nvmem_config config;
	struct nvmem_device *nvmem;

	memset(&config, 0, sizeof(config));

	config.name = "nvm_non_active";
	config.reg_write = reg_write;
	config.root_only = true;
	config.id = nvm->id;
	config.stride = 4;
	config.word_size = 4;
	config.size = NVM_MAX_SIZE;
	config.dev = nvm->dev;
	config.owner = THIS_MODULE;
	config.priv = nvm;

	nvmem = nvmem_register(&config);
	if (IS_ERR(nvmem))
		return PTR_ERR(nvmem);

	nvm->non_active = nvmem;
	return 0;
}

/**
 * tb_nvm_free() - Release NVM and its resources
 * @nvm: NVM structure to release
 *
 * Releases NVM and the NVMem devices if they were registered.
 */
void tb_nvm_free(struct tb_nvm *nvm)
{
	if (nvm) {
		nvmem_unregister(nvm->non_active);
		nvmem_unregister(nvm->active);
		vfree(nvm->buf);
		ida_free(&nvm_ida, nvm->id);
	}
	kfree(nvm);
}

/**
 * tb_nvm_read_data() - Read data from NVM
 * @address: Start address on the flash
 * @buf: Buffer where the read data is copied
 * @size: Size of the buffer in bytes
 * @retries: Number of retries if block read fails
 * @read_block: Function that reads block from the flash
 * @read_block_data: Data passsed to @read_block
 *
 * This is a generic function that reads data from NVM or NVM like
 * device.
 *
 * Return: %0 on success, negative errno otherwise.
 */
int tb_nvm_read_data(unsigned int address, void *buf, size_t size,
		     unsigned int retries, read_block_fn read_block,
		     void *read_block_data)
{
	do {
		unsigned int dwaddress, dwords, offset;
		u8 data[NVM_DATA_DWORDS * 4];
		size_t nbytes;
		int ret;

		offset = address & 3;
		nbytes = min_t(size_t, size + offset, NVM_DATA_DWORDS * 4);

		dwaddress = address / 4;
		dwords = ALIGN(nbytes, 4) / 4;

		ret = read_block(read_block_data, dwaddress, data, dwords);
		if (ret) {
			if (ret != -ENODEV && retries--)
				continue;
			return ret;
		}

		nbytes -= offset;
		memcpy(buf, data + offset, nbytes);

		size -= nbytes;
		address += nbytes;
		buf += nbytes;
	} while (size > 0);

	return 0;
}

/**
 * tb_nvm_write_data() - Write data to NVM
 * @address: Start address on the flash
 * @buf: Buffer where the data is copied from
 * @size: Size of the buffer in bytes
 * @retries: Number of retries if the block write fails
 * @write_block: Function that writes block to the flash
 * @write_block_data: Data passed to @write_block
 *
 * This is generic function that writes data to NVM or NVM like device.
 *
 * Return: %0 on success, negative errno otherwise.
 */
int tb_nvm_write_data(unsigned int address, const void *buf, size_t size,
		      unsigned int retries, write_block_fn write_block,
		      void *write_block_data)
{
	do {
		unsigned int offset, dwaddress;
		u8 data[NVM_DATA_DWORDS * 4];
		size_t nbytes;
		int ret;

		offset = address & 3;
		nbytes = min_t(u32, size + offset, NVM_DATA_DWORDS * 4);

		memcpy(data + offset, buf, nbytes);

		dwaddress = address / 4;
		ret = write_block(write_block_data, dwaddress, data, nbytes / 4);
		if (ret) {
			if (ret == -ETIMEDOUT) {
				if (retries--)
					continue;
				ret = -EIO;
			}
			return ret;
		}

		size -= nbytes;
		address += nbytes;
		buf += nbytes;
	} while (size > 0);

	return 0;
}

void tb_nvm_exit(void)
{
	ida_destroy(&nvm_ida);
}
