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