/* Copyright 2013-2016 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 <pci.h>
#include <pci-virt.h>

void pci_virt_cfg_read_raw(struct pci_virt_device *pvd,
			   uint32_t space, uint32_t offset,
			   uint32_t size, uint32_t *data)
{
	uint32_t i;

	if (space >= PCI_VIRT_CFG_MAX || !pvd->config[space])
		return;

	for (*data = 0, i = 0; i < size; i++)
		*data |= ((uint32_t)(pvd->config[space][offset + i]) << (i * 8));
}

void pci_virt_cfg_write_raw(struct pci_virt_device *pvd,
			    uint32_t space, uint32_t offset,
			    uint32_t size, uint32_t data)
{
	int i;

	if (space >= PCI_VIRT_CFG_MAX || !pvd->config[space])
		return;

	for (i = 0; i < size; i++) {
		pvd->config[space][offset + i] = data;
		data = (data >> 8);
	}
}

static struct pci_cfg_reg_filter *pci_virt_find_filter(
					struct pci_virt_device *pvd,
					uint32_t start, uint32_t len)
{
	struct pci_cfg_reg_filter *pcrf;

	if (!pvd || !len || start >= pvd->cfg_size)
		return NULL;

	/* Return filter if there is overlapped region. We don't
	 * require strict matching for more flexibility. It also
	 * means the associated handler should validate the register
	 * offset and length.
	 */
	list_for_each(&pvd->pcrf, pcrf, link) {
		if (start < (pcrf->start + pcrf->len) &&
		    (start + len) > pcrf->start)
			return pcrf;
	}

	return NULL;
}

struct pci_cfg_reg_filter *pci_virt_add_filter(struct pci_virt_device *pvd,
					       uint32_t start,
					       uint32_t len,
					       uint32_t flags,
					       pci_cfg_reg_func func,
					       void *data)
{
	struct pci_cfg_reg_filter *pcrf;

	if (!pvd || !len || (start + len) >= pvd->cfg_size)
		return NULL;
	if (!(flags & PCI_REG_FLAG_MASK))
		return NULL;

	pcrf = pci_virt_find_filter(pvd, start, len);
	if (pcrf) {
		prlog(PR_ERR, "%s: Filter [%x, %x] overlapped with [%x, %x]\n",
		      __func__, start, len, pcrf->start, pcrf->len);
		return NULL;
	}

	pcrf = zalloc(sizeof(*pcrf));
	if (!pcrf) {
		prlog(PR_ERR, "%s: Out of memory!\n", __func__);
		return NULL;
	}

	pcrf->start = start;
	pcrf->len   = len;
	pcrf->flags = flags;
	pcrf->func  = func;
	pcrf->data  = data;
	list_add_tail(&pvd->pcrf, &pcrf->link);

	return pcrf;
}

struct pci_virt_device *pci_virt_find_device(struct phb *phb,
					     uint32_t bdfn)
{
	struct pci_virt_device *pvd;

	list_for_each(&phb->virt_devices, pvd, node) {
		if (pvd->bdfn == bdfn)
			return pvd;
	}

	return NULL;
}

static inline bool pci_virt_cfg_valid(struct pci_virt_device *pvd,
				      uint32_t offset, uint32_t size)
{
	if ((offset + size) > pvd->cfg_size)
		return false;

	if (!size || (size > 4))
		return false;

	if ((size & (size - 1)) || (offset & (size - 1)))
		return false;

	return true;
}

int64_t pci_virt_cfg_read(struct phb *phb, uint32_t bdfn,
			  uint32_t offset, uint32_t size,
			  uint32_t *data)
{
	struct pci_virt_device *pvd;
	struct pci_cfg_reg_filter *pcrf;
	int64_t ret = OPAL_SUCCESS;

	*data = 0xffffffff;

	/* Search for PCI virtual device */
	pvd = pci_virt_find_device(phb, bdfn);
	if (!pvd)
		return OPAL_PARAMETER;

	/* Check if config address is valid or not */
	if (!pci_virt_cfg_valid(pvd, offset, size))
		return OPAL_PARAMETER;

	/* The value is fetched from the normal config space when the
	 * trap handler returns OPAL_PARTIAL. Otherwise, the trap handler
	 * should provide the return value.
	 */
	pcrf = pci_virt_find_filter(pvd, offset, size);
	if (!pcrf || !pcrf->func || !(pcrf->flags & PCI_REG_FLAG_READ))
		goto out;

	ret = pcrf->func(pvd, pcrf, offset, size, data, false);
	if (ret != OPAL_PARTIAL)
		return ret;
out:
	pci_virt_cfg_read_raw(pvd, PCI_VIRT_CFG_NORMAL, offset, size, data);
	return OPAL_SUCCESS;
}

int64_t pci_virt_cfg_write(struct phb *phb, uint32_t bdfn,
			   uint32_t offset, uint32_t size,
			   uint32_t data)
{
	struct pci_virt_device *pvd;
	struct pci_cfg_reg_filter *pcrf;
	uint32_t val, v, r, c, i;
	int64_t ret = OPAL_SUCCESS;

	/* Search for PCI virtual device */
	pvd = pci_virt_find_device(phb, bdfn);
	if (!pvd)
		return OPAL_PARAMETER;

	/* Check if config address is valid or not */
	if (!pci_virt_cfg_valid(pvd, offset, size))
		return OPAL_PARAMETER;

	/* The value is written to the config space if the trap handler
	 * returns OPAL_PARTIAL. Otherwise, the value to be written is
	 * dropped.
	 */
	pcrf = pci_virt_find_filter(pvd, offset, size);
	if (!pcrf || !pcrf->func || !(pcrf->flags & PCI_REG_FLAG_WRITE))
		goto out;

	ret = pcrf->func(pvd, pcrf, offset, size, &data, true);
	if (ret != OPAL_PARTIAL)
		return ret;
out:
	val = data;
	for (i = 0; i < size; i++) {
		PCI_VIRT_CFG_NORMAL_RD(pvd, offset + i, 1, &v);
		PCI_VIRT_CFG_RDONLY_RD(pvd, offset + i, 1, &r);
		PCI_VIRT_CFG_W1CLR_RD(pvd, offset + i, 1, &c);

		/* Drop read-only bits */
		val &= ~(r << (i * 8));
		val |= (r & v) << (i * 8);

		/* Drop W1C bits */
		val &= ~(val & ((c & v) << (i * 8)));
	}

	PCI_VIRT_CFG_NORMAL_WR(pvd, offset, size, val);
	return OPAL_SUCCESS;
}

struct pci_virt_device *pci_virt_add_device(struct phb *phb, uint32_t bdfn,
					    uint32_t cfg_size, void *data)
{
	struct pci_virt_device *pvd;
	uint8_t *cfg;
	uint32_t i;

	/* The standard config header size is 64 bytes */
	if (!phb || (bdfn & 0xffff0000) || (cfg_size < 64))
		return NULL;

	/* Check if the bdfn is available */
	pvd = pci_virt_find_device(phb, bdfn);
	if (pvd) {
		prlog(PR_ERR, "%s: bdfn 0x%x was reserved\n",
		      __func__, bdfn);
		return NULL;
	}

	/* Populate the PCI virtual device */
	pvd = zalloc(sizeof(*pvd));
	if (!pvd) {
		prlog(PR_ERR, "%s: Cannot alloate PCI virtual device (0x%x)\n",
		      __func__, bdfn);
		return NULL;
	}

	cfg = zalloc(cfg_size * PCI_VIRT_CFG_MAX);
	if (!cfg) {
		prlog(PR_ERR, "%s: Cannot allocate config space (0x%x)\n",
		      __func__, bdfn);
		free(pvd);
		return NULL;
	}

	for (i = 0; i < PCI_VIRT_CFG_MAX; i++, cfg += cfg_size)
		pvd->config[i] = cfg;

	pvd->bdfn     = bdfn;
	pvd->cfg_size = cfg_size;
	pvd->data     = data;
	list_head_init(&pvd->pcrf);
	list_add_tail(&phb->virt_devices, &pvd->node);

	return pvd;
}
