// SPDX-License-Identifier: GPL-2.0-only
/*
 * WHCI UWB Multi-interface Controller enumerator.
 *
 * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
 */
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include "include/whci.h"
#include "include/umc.h"

struct whci_card {
	struct pci_dev *pci;
	void __iomem *uwbbase;
	u8 n_caps;
	struct umc_dev *devs[0];
};


/* Fix faulty HW :( */
static
u64 whci_capdata_quirks(struct whci_card *card, u64 capdata)
{
	u64 capdata_orig = capdata;
	struct pci_dev *pci_dev = card->pci;
	if (pci_dev->vendor == PCI_VENDOR_ID_INTEL
	    && (pci_dev->device == 0x0c3b || pci_dev->device == 0004)
	    && pci_dev->class == 0x0d1010) {
		switch (UWBCAPDATA_TO_CAP_ID(capdata)) {
			/* WLP capability has 0x100 bytes of aperture */
		case 0x80:
			capdata |= 0x40 << 8; break;
			/* WUSB capability has 0x80 bytes of aperture
			 * and ID is 1 */
		case 0x02:
			capdata &= ~0xffff;
			capdata |= 0x2001;
			break;
		}
	}
	if (capdata_orig != capdata)
		dev_warn(&pci_dev->dev,
			 "PCI v%04x d%04x c%06x#%02x: "
			 "corrected capdata from %016Lx to %016Lx\n",
			 pci_dev->vendor, pci_dev->device, pci_dev->class,
			 (unsigned)UWBCAPDATA_TO_CAP_ID(capdata),
			 (unsigned long long)capdata_orig,
			 (unsigned long long)capdata);
	return capdata;
}


/**
 * whci_wait_for - wait for a WHCI register to be set
 *
 * Polls (for at most @max_ms ms) until '*@reg & @mask == @result'.
 */
int whci_wait_for(struct device *dev, u32 __iomem *reg, u32 mask, u32 result,
	unsigned long max_ms, const char *tag)
{
	unsigned t = 0;
	u32 val;
	for (;;) {
		val = le_readl(reg);
		if ((val & mask) == result)
			break;
		if (t >= max_ms) {
			dev_err(dev, "%s timed out\n", tag);
			return -ETIMEDOUT;
		}
		msleep(10);
		t += 10;
	}
	return 0;
}
EXPORT_SYMBOL_GPL(whci_wait_for);


/*
 * NOTE: the capinfo and capdata registers are slightly different
 *       (size and cap-id fields). So for cap #0, we need to fill
 *       in. Size comes from the size of the register block
 *       (statically calculated); cap_id comes from nowhere, we use
 *       zero, that is reserved, for the radio controller, because
 *       none was defined at the spec level.
 */
static int whci_add_cap(struct whci_card *card, int n)
{
	struct umc_dev *umc;
	u64 capdata;
	int bar, err;

	umc = umc_device_create(&card->pci->dev, n);
	if (umc == NULL)
		return -ENOMEM;

	capdata = le_readq(card->uwbbase + UWBCAPDATA(n));

	bar = UWBCAPDATA_TO_BAR(capdata) << 1;

	capdata = whci_capdata_quirks(card, capdata);
	/* Capability 0 is the radio controller. It's size is 32
	 * bytes (WHCI0.95[2.3, T2-9]). */
	umc->version         = UWBCAPDATA_TO_VERSION(capdata);
	umc->cap_id          = n == 0 ? 0 : UWBCAPDATA_TO_CAP_ID(capdata);
	umc->bar	     = bar;
	umc->resource.start  = pci_resource_start(card->pci, bar)
		+ UWBCAPDATA_TO_OFFSET(capdata);
	umc->resource.end    = umc->resource.start
		+ (n == 0 ? 0x20 : UWBCAPDATA_TO_SIZE(capdata)) - 1;
	umc->resource.name   = dev_name(&umc->dev);
	umc->resource.flags  = card->pci->resource[bar].flags;
	umc->resource.parent = &card->pci->resource[bar];
	umc->irq             = card->pci->irq;

	err = umc_device_register(umc);
	if (err < 0)
		goto error;
	card->devs[n] = umc;
	return 0;

error:
	kfree(umc);
	return err;
}

static void whci_del_cap(struct whci_card *card, int n)
{
	struct umc_dev *umc = card->devs[n];

	umc_device_unregister(umc);
}

static int whci_n_caps(struct pci_dev *pci)
{
	void __iomem *uwbbase;
	u64 capinfo;

	uwbbase = pci_iomap(pci, 0, 8);
	if (!uwbbase)
		return -ENOMEM;
	capinfo = le_readq(uwbbase + UWBCAPINFO);
	pci_iounmap(pci, uwbbase);

	return UWBCAPINFO_TO_N_CAPS(capinfo);
}

static int whci_probe(struct pci_dev *pci, const struct pci_device_id *id)
{
	struct whci_card *card;
	int err, n_caps, n;

	err = pci_enable_device(pci);
	if (err < 0)
		goto error;
	pci_enable_msi(pci);
	pci_set_master(pci);
	err = -ENXIO;
	if (!pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
		pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
	else if (!pci_set_dma_mask(pci, DMA_BIT_MASK(32)))
		pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32));
	else
		goto error_dma;

	err = n_caps = whci_n_caps(pci);
	if (n_caps < 0)
		goto error_ncaps;

	err = -ENOMEM;
	card = kzalloc(sizeof(struct whci_card)
		       + sizeof(struct umc_dev *) * (n_caps + 1),
		       GFP_KERNEL);
	if (card == NULL)
		goto error_kzalloc;
	card->pci = pci;
	card->n_caps = n_caps;

	err = -EBUSY;
	if (!request_mem_region(pci_resource_start(pci, 0),
				UWBCAPDATA_SIZE(card->n_caps),
				"whci (capability data)"))
		goto error_request_memregion;
	err = -ENOMEM;
	card->uwbbase = pci_iomap(pci, 0, UWBCAPDATA_SIZE(card->n_caps));
	if (!card->uwbbase)
		goto error_iomap;

	/* Add each capability. */
	for (n = 0; n <= card->n_caps; n++) {
		err = whci_add_cap(card, n);
		if (err < 0 && n == 0) {
			dev_err(&pci->dev, "cannot bind UWB radio controller:"
				" %d\n", err);
			goto error_bind;
		}
		if (err < 0)
			dev_warn(&pci->dev, "warning: cannot bind capability "
				 "#%u: %d\n", n, err);
	}
	pci_set_drvdata(pci, card);
	return 0;

error_bind:
	pci_iounmap(pci, card->uwbbase);
error_iomap:
	release_mem_region(pci_resource_start(pci, 0), UWBCAPDATA_SIZE(card->n_caps));
error_request_memregion:
	kfree(card);
error_kzalloc:
error_ncaps:
error_dma:
	pci_disable_msi(pci);
	pci_disable_device(pci);
error:
	return err;
}

static void whci_remove(struct pci_dev *pci)
{
	struct whci_card *card = pci_get_drvdata(pci);
	int n;

	pci_set_drvdata(pci, NULL);
	/* Unregister each capability in reverse (so the master device
	 * is unregistered last). */
	for (n = card->n_caps; n >= 0 ; n--)
		whci_del_cap(card, n);
	pci_iounmap(pci, card->uwbbase);
	release_mem_region(pci_resource_start(pci, 0), UWBCAPDATA_SIZE(card->n_caps));
	kfree(card);
	pci_disable_msi(pci);
	pci_disable_device(pci);
}

static struct pci_device_id whci_id_table[] = {
	{ PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI, ~0) },
	{ 0 },
};
MODULE_DEVICE_TABLE(pci, whci_id_table);


static struct pci_driver whci_driver = {
	.name     = "whci",
	.id_table = whci_id_table,
	.probe    = whci_probe,
	.remove   = whci_remove,
};

module_pci_driver(whci_driver);
MODULE_DESCRIPTION("WHCI UWB Multi-interface Controller enumerator");
MODULE_AUTHOR("Cambridge Silicon Radio Ltd.");
MODULE_LICENSE("GPL");
