1/* 2 * Intel MIC Platform Software Stack (MPSS) 3 * 4 * Copyright(c) 2013 Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License, version 2, as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * The full GNU General Public License is included in this distribution in 16 * the file called "COPYING". 17 * 18 * Disclaimer: The codes contained in these modules may be specific to 19 * the Intel Software Development Platform codenamed: Knights Ferry, and 20 * the Intel product codenamed: Knights Corner, and are not backward 21 * compatible with other Intel products. Additionally, Intel will NOT 22 * support the codes or instruction set in future products. 23 * 24 * Intel MIC Card driver. 25 * 26 */ 27#include <linux/module.h> 28#include <linux/pci.h> 29#include <linux/platform_device.h> 30 31#include "../common/mic_dev.h" 32#include "mic_device.h" 33#include "mic_x100.h" 34 35static const char mic_driver_name[] = "mic"; 36 37static struct mic_driver g_drv; 38 39/** 40 * mic_read_spad - read from the scratchpad register 41 * @mdev: pointer to mic_device instance 42 * @idx: index to scratchpad register, 0 based 43 * 44 * This function allows reading of the 32bit scratchpad register. 45 * 46 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 47 */ 48u32 mic_read_spad(struct mic_device *mdev, unsigned int idx) 49{ 50 return mic_mmio_read(&mdev->mmio, 51 MIC_X100_SBOX_BASE_ADDRESS + 52 MIC_X100_SBOX_SPAD0 + idx * 4); 53} 54 55/** 56 * __mic_send_intr - Send interrupt to Host. 57 * @mdev: pointer to mic_device instance 58 * @doorbell: Doorbell number. 59 */ 60void mic_send_intr(struct mic_device *mdev, int doorbell) 61{ 62 struct mic_mw *mw = &mdev->mmio; 63 64 if (doorbell > MIC_X100_MAX_DOORBELL_IDX) 65 return; 66 /* Ensure that the interrupt is ordered w.r.t previous stores. */ 67 wmb(); 68 mic_mmio_write(mw, MIC_X100_SBOX_SDBIC0_DBREQ_BIT, 69 MIC_X100_SBOX_BASE_ADDRESS + 70 (MIC_X100_SBOX_SDBIC0 + (4 * doorbell))); 71} 72 73/** 74 * mic_ack_interrupt - Device specific interrupt handling. 75 * @mdev: pointer to mic_device instance 76 * 77 * Returns: bitmask of doorbell events triggered. 78 */ 79u32 mic_ack_interrupt(struct mic_device *mdev) 80{ 81 return 0; 82} 83 84static inline int mic_get_sbox_irq(int db) 85{ 86 return MIC_X100_IRQ_BASE + db; 87} 88 89static inline int mic_get_rdmasr_irq(int index) 90{ 91 return MIC_X100_RDMASR_IRQ_BASE + index; 92} 93 94/** 95 * mic_hw_intr_init - Initialize h/w specific interrupt 96 * information. 97 * @mdrv: pointer to mic_driver 98 */ 99void mic_hw_intr_init(struct mic_driver *mdrv) 100{ 101 mdrv->intr_info.num_intr = MIC_X100_NUM_SBOX_IRQ + 102 MIC_X100_NUM_RDMASR_IRQ; 103} 104 105/** 106 * mic_db_to_irq - Retrieve irq number corresponding to a doorbell. 107 * @mdrv: pointer to mic_driver 108 * @db: The doorbell obtained for which the irq is needed. Doorbell 109 * may correspond to an sbox doorbell or an rdmasr index. 110 * 111 * Returns the irq corresponding to the doorbell. 112 */ 113int mic_db_to_irq(struct mic_driver *mdrv, int db) 114{ 115 int rdmasr_index; 116 if (db < MIC_X100_NUM_SBOX_IRQ) { 117 return mic_get_sbox_irq(db); 118 } else { 119 rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ + 120 MIC_X100_RDMASR_IRQ_BASE; 121 return mic_get_rdmasr_irq(rdmasr_index); 122 } 123} 124 125/* 126 * mic_card_map - Allocate virtual address for a remote memory region. 127 * @mdev: pointer to mic_device instance. 128 * @addr: Remote DMA address. 129 * @size: Size of the region. 130 * 131 * Returns: Virtual address backing the remote memory region. 132 */ 133void __iomem * 134mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size) 135{ 136 return ioremap(addr, size); 137} 138 139/* 140 * mic_card_unmap - Unmap the virtual address for a remote memory region. 141 * @mdev: pointer to mic_device instance. 142 * @addr: Virtual address for remote memory region. 143 * 144 * Returns: None. 145 */ 146void mic_card_unmap(struct mic_device *mdev, void __iomem *addr) 147{ 148 iounmap(addr); 149} 150 151static inline struct mic_driver *mbdev_to_mdrv(struct mbus_device *mbdev) 152{ 153 return dev_get_drvdata(mbdev->dev.parent); 154} 155 156static struct mic_irq * 157_mic_request_threaded_irq(struct mbus_device *mbdev, 158 irq_handler_t handler, irq_handler_t thread_fn, 159 const char *name, void *data, int intr_src) 160{ 161 int rc = 0; 162 unsigned int irq = intr_src; 163 unsigned long cookie = irq; 164 165 rc = request_threaded_irq(irq, handler, thread_fn, 0, name, data); 166 if (rc) { 167 dev_err(mbdev_to_mdrv(mbdev)->dev, 168 "request_threaded_irq failed rc = %d\n", rc); 169 return ERR_PTR(rc); 170 } 171 return (struct mic_irq *)cookie; 172} 173 174static void _mic_free_irq(struct mbus_device *mbdev, 175 struct mic_irq *cookie, void *data) 176{ 177 unsigned long irq = (unsigned long)cookie; 178 free_irq(irq, data); 179} 180 181static void _mic_ack_interrupt(struct mbus_device *mbdev, int num) 182{ 183 mic_ack_interrupt(&mbdev_to_mdrv(mbdev)->mdev); 184} 185 186static struct mbus_hw_ops mbus_hw_ops = { 187 .request_threaded_irq = _mic_request_threaded_irq, 188 .free_irq = _mic_free_irq, 189 .ack_interrupt = _mic_ack_interrupt, 190}; 191 192static int __init mic_probe(struct platform_device *pdev) 193{ 194 struct mic_driver *mdrv = &g_drv; 195 struct mic_device *mdev = &mdrv->mdev; 196 int rc = 0; 197 198 mdrv->dev = &pdev->dev; 199 snprintf(mdrv->name, sizeof(mic_driver_name), mic_driver_name); 200 201 mdev->mmio.pa = MIC_X100_MMIO_BASE; 202 mdev->mmio.len = MIC_X100_MMIO_LEN; 203 mdev->mmio.va = devm_ioremap(&pdev->dev, MIC_X100_MMIO_BASE, 204 MIC_X100_MMIO_LEN); 205 if (!mdev->mmio.va) { 206 dev_err(&pdev->dev, "Cannot remap MMIO BAR\n"); 207 rc = -EIO; 208 goto done; 209 } 210 mic_hw_intr_init(mdrv); 211 platform_set_drvdata(pdev, mdrv); 212 mdrv->dma_mbdev = mbus_register_device(mdrv->dev, MBUS_DEV_DMA_MIC, 213 NULL, &mbus_hw_ops, 214 mdrv->mdev.mmio.va); 215 if (IS_ERR(mdrv->dma_mbdev)) { 216 rc = PTR_ERR(mdrv->dma_mbdev); 217 dev_err(&pdev->dev, "mbus_add_device failed rc %d\n", rc); 218 goto done; 219 } 220 rc = mic_driver_init(mdrv); 221 if (rc) { 222 dev_err(&pdev->dev, "mic_driver_init failed rc %d\n", rc); 223 goto remove_dma; 224 } 225done: 226 return rc; 227remove_dma: 228 mbus_unregister_device(mdrv->dma_mbdev); 229 return rc; 230} 231 232static int mic_remove(struct platform_device *pdev) 233{ 234 struct mic_driver *mdrv = &g_drv; 235 236 mic_driver_uninit(mdrv); 237 mbus_unregister_device(mdrv->dma_mbdev); 238 return 0; 239} 240 241static void mic_platform_shutdown(struct platform_device *pdev) 242{ 243 mic_remove(pdev); 244} 245 246static struct platform_device mic_platform_dev = { 247 .name = mic_driver_name, 248 .id = 0, 249 .num_resources = 0, 250}; 251 252static struct platform_driver __refdata mic_platform_driver = { 253 .probe = mic_probe, 254 .remove = mic_remove, 255 .shutdown = mic_platform_shutdown, 256 .driver = { 257 .name = mic_driver_name, 258 }, 259}; 260 261static int __init mic_init(void) 262{ 263 int ret; 264 struct cpuinfo_x86 *c = &cpu_data(0); 265 266 if (!(c->x86 == 11 && c->x86_model == 1)) { 267 ret = -ENODEV; 268 pr_err("%s not running on X100 ret %d\n", __func__, ret); 269 goto done; 270 } 271 272 mic_init_card_debugfs(); 273 ret = platform_device_register(&mic_platform_dev); 274 if (ret) { 275 pr_err("platform_device_register ret %d\n", ret); 276 goto cleanup_debugfs; 277 } 278 ret = platform_driver_register(&mic_platform_driver); 279 if (ret) { 280 pr_err("platform_driver_register ret %d\n", ret); 281 goto device_unregister; 282 } 283 return ret; 284 285device_unregister: 286 platform_device_unregister(&mic_platform_dev); 287cleanup_debugfs: 288 mic_exit_card_debugfs(); 289done: 290 return ret; 291} 292 293static void __exit mic_exit(void) 294{ 295 platform_driver_unregister(&mic_platform_driver); 296 platform_device_unregister(&mic_platform_dev); 297 mic_exit_card_debugfs(); 298} 299 300module_init(mic_init); 301module_exit(mic_exit); 302 303MODULE_AUTHOR("Intel Corporation"); 304MODULE_DESCRIPTION("Intel(R) MIC X100 Card driver"); 305MODULE_LICENSE("GPL v2"); 306