diff options
Diffstat (limited to 'drivers/misc/mic/card/mic_x100.c')
| -rw-r--r-- | drivers/misc/mic/card/mic_x100.c | 256 | 
1 files changed, 256 insertions, 0 deletions
diff --git a/drivers/misc/mic/card/mic_x100.c b/drivers/misc/mic/card/mic_x100.c new file mode 100644 index 00000000000..2868945c9a4 --- /dev/null +++ b/drivers/misc/mic/card/mic_x100.c @@ -0,0 +1,256 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, 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. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Disclaimer: The codes contained in these modules may be specific to + * the Intel Software Development Platform codenamed: Knights Ferry, and + * the Intel product codenamed: Knights Corner, and are not backward + * compatible with other Intel products. Additionally, Intel will NOT + * support the codes or instruction set in future products. + * + * Intel MIC Card driver. + * + */ +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/platform_device.h> + +#include "../common/mic_dev.h" +#include "mic_device.h" +#include "mic_x100.h" + +static const char mic_driver_name[] = "mic"; + +static struct mic_driver g_drv; + +/** + * mic_read_spad - read from the scratchpad register + * @mdev: pointer to mic_device instance + * @idx: index to scratchpad register, 0 based + * + * This function allows reading of the 32bit scratchpad register. + * + * RETURNS: An appropriate -ERRNO error value on error, or zero for success. + */ +u32 mic_read_spad(struct mic_device *mdev, unsigned int idx) +{ +	return mic_mmio_read(&mdev->mmio, +		MIC_X100_SBOX_BASE_ADDRESS + +		MIC_X100_SBOX_SPAD0 + idx * 4); +} + +/** + * __mic_send_intr - Send interrupt to Host. + * @mdev: pointer to mic_device instance + * @doorbell: Doorbell number. + */ +void mic_send_intr(struct mic_device *mdev, int doorbell) +{ +	struct mic_mw *mw = &mdev->mmio; + +	if (doorbell > MIC_X100_MAX_DOORBELL_IDX) +		return; +	/* Ensure that the interrupt is ordered w.r.t previous stores. */ +	wmb(); +	mic_mmio_write(mw, MIC_X100_SBOX_SDBIC0_DBREQ_BIT, +		       MIC_X100_SBOX_BASE_ADDRESS + +		       (MIC_X100_SBOX_SDBIC0 + (4 * doorbell))); +} + +/** + * mic_ack_interrupt - Device specific interrupt handling. + * @mdev: pointer to mic_device instance + * + * Returns: bitmask of doorbell events triggered. + */ +u32 mic_ack_interrupt(struct mic_device *mdev) +{ +	return 0; +} + +static inline int mic_get_sbox_irq(int db) +{ +	return MIC_X100_IRQ_BASE + db; +} + +static inline int mic_get_rdmasr_irq(int index) +{ +	return  MIC_X100_RDMASR_IRQ_BASE + index; +} + +/** + * mic_hw_intr_init - Initialize h/w specific interrupt + * information. + * @mdrv: pointer to mic_driver + */ +void mic_hw_intr_init(struct mic_driver *mdrv) +{ +	mdrv->intr_info.num_intr = MIC_X100_NUM_SBOX_IRQ + +				MIC_X100_NUM_RDMASR_IRQ; +} + +/** + * mic_db_to_irq - Retrieve irq number corresponding to a doorbell. + * @mdrv: pointer to mic_driver + * @db: The doorbell obtained for which the irq is needed. Doorbell + * may correspond to an sbox doorbell or an rdmasr index. + * + * Returns the irq corresponding to the doorbell. + */ +int mic_db_to_irq(struct mic_driver *mdrv, int db) +{ +	int rdmasr_index; +	if (db < MIC_X100_NUM_SBOX_IRQ) { +		return mic_get_sbox_irq(db); +	} else { +		rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ + +			MIC_X100_RDMASR_IRQ_BASE; +		return mic_get_rdmasr_irq(rdmasr_index); +	} +} + +/* + * mic_card_map - Allocate virtual address for a remote memory region. + * @mdev: pointer to mic_device instance. + * @addr: Remote DMA address. + * @size: Size of the region. + * + * Returns: Virtual address backing the remote memory region. + */ +void __iomem * +mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size) +{ +	return ioremap(addr, size); +} + +/* + * mic_card_unmap - Unmap the virtual address for a remote memory region. + * @mdev: pointer to mic_device instance. + * @addr: Virtual address for remote memory region. + * + * Returns: None. + */ +void mic_card_unmap(struct mic_device *mdev, void __iomem *addr) +{ +	iounmap(addr); +} + +static int __init mic_probe(struct platform_device *pdev) +{ +	struct mic_driver *mdrv = &g_drv; +	struct mic_device *mdev = &mdrv->mdev; +	int rc = 0; + +	mdrv->dev = &pdev->dev; +	snprintf(mdrv->name, sizeof(mic_driver_name), mic_driver_name); + +	mdev->mmio.pa = MIC_X100_MMIO_BASE; +	mdev->mmio.len = MIC_X100_MMIO_LEN; +	mdev->mmio.va = ioremap(MIC_X100_MMIO_BASE, MIC_X100_MMIO_LEN); +	if (!mdev->mmio.va) { +		dev_err(&pdev->dev, "Cannot remap MMIO BAR\n"); +		rc = -EIO; +		goto done; +	} +	mic_hw_intr_init(mdrv); +	rc = mic_driver_init(mdrv); +	if (rc) { +		dev_err(&pdev->dev, "mic_driver_init failed rc %d\n", rc); +		goto iounmap; +	} +done: +	return rc; +iounmap: +	iounmap(mdev->mmio.va); +	return rc; +} + +static int mic_remove(struct platform_device *pdev) +{ +	struct mic_driver *mdrv = &g_drv; +	struct mic_device *mdev = &mdrv->mdev; + +	mic_driver_uninit(mdrv); +	iounmap(mdev->mmio.va); +	return 0; +} + +static void mic_platform_shutdown(struct platform_device *pdev) +{ +	mic_remove(pdev); +} + +static struct platform_device mic_platform_dev = { +	.name = mic_driver_name, +	.id   = 0, +	.num_resources = 0, +}; + +static struct platform_driver __refdata mic_platform_driver = { +	.probe = mic_probe, +	.remove = mic_remove, +	.shutdown = mic_platform_shutdown, +	.driver         = { +		.name   = mic_driver_name, +		.owner	= THIS_MODULE, +	}, +}; + +static int __init mic_init(void) +{ +	int ret; +	struct cpuinfo_x86 *c = &cpu_data(0); + +	if (!(c->x86 == 11 && c->x86_model == 1)) { +		ret = -ENODEV; +		pr_err("%s not running on X100 ret %d\n", __func__, ret); +		goto done; +	} + +	mic_init_card_debugfs(); +	ret = platform_device_register(&mic_platform_dev); +	if (ret) { +		pr_err("platform_device_register ret %d\n", ret); +		goto cleanup_debugfs; +	} +	ret = platform_driver_register(&mic_platform_driver); +	if (ret) { +		pr_err("platform_driver_register ret %d\n", ret); +		goto device_unregister; +	} +	return ret; + +device_unregister: +	platform_device_unregister(&mic_platform_dev); +cleanup_debugfs: +	mic_exit_card_debugfs(); +done: +	return ret; +} + +static void __exit mic_exit(void) +{ +	platform_driver_unregister(&mic_platform_driver); +	platform_device_unregister(&mic_platform_dev); +	mic_exit_card_debugfs(); +} + +module_init(mic_init); +module_exit(mic_exit); + +MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("Intel(R) MIC X100 Card driver"); +MODULE_LICENSE("GPL v2");  | 
