linux/arch/powerpc/platforms/cell/axon_msi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright 2007, Michael Ellerman, IBM Corporation.
   4 */
   5
   6
   7#include <linux/interrupt.h>
   8#include <linux/irq.h>
   9#include <linux/kernel.h>
  10#include <linux/pci.h>
  11#include <linux/msi.h>
  12#include <linux/export.h>
  13#include <linux/of_platform.h>
  14#include <linux/slab.h>
  15
  16#include <asm/debugfs.h>
  17#include <asm/dcr.h>
  18#include <asm/machdep.h>
  19#include <asm/prom.h>
  20
  21#include "cell.h"
  22
  23/*
  24 * MSIC registers, specified as offsets from dcr_base
  25 */
  26#define MSIC_CTRL_REG   0x0
  27
  28/* Base Address registers specify FIFO location in BE memory */
  29#define MSIC_BASE_ADDR_HI_REG   0x3
  30#define MSIC_BASE_ADDR_LO_REG   0x4
  31
  32/* Hold the read/write offsets into the FIFO */
  33#define MSIC_READ_OFFSET_REG    0x5
  34#define MSIC_WRITE_OFFSET_REG   0x6
  35
  36
  37/* MSIC control register flags */
  38#define MSIC_CTRL_ENABLE                0x0001
  39#define MSIC_CTRL_FIFO_FULL_ENABLE      0x0002
  40#define MSIC_CTRL_IRQ_ENABLE            0x0008
  41#define MSIC_CTRL_FULL_STOP_ENABLE      0x0010
  42
  43/*
  44 * The MSIC can be configured to use a FIFO of 32KB, 64KB, 128KB or 256KB.
  45 * Currently we're using a 64KB FIFO size.
  46 */
  47#define MSIC_FIFO_SIZE_SHIFT    16
  48#define MSIC_FIFO_SIZE_BYTES    (1 << MSIC_FIFO_SIZE_SHIFT)
  49
  50/*
  51 * To configure the FIFO size as (1 << n) bytes, we write (n - 15) into bits
  52 * 8-9 of the MSIC control reg.
  53 */
  54#define MSIC_CTRL_FIFO_SIZE     (((MSIC_FIFO_SIZE_SHIFT - 15) << 8) & 0x300)
  55
  56/*
  57 * We need to mask the read/write offsets to make sure they stay within
  58 * the bounds of the FIFO. Also they should always be 16-byte aligned.
  59 */
  60#define MSIC_FIFO_SIZE_MASK     ((MSIC_FIFO_SIZE_BYTES - 1) & ~0xFu)
  61
  62/* Each entry in the FIFO is 16 bytes, the first 4 bytes hold the irq # */
  63#define MSIC_FIFO_ENTRY_SIZE    0x10
  64
  65
  66struct axon_msic {
  67        struct irq_domain *irq_domain;
  68        __le32 *fifo_virt;
  69        dma_addr_t fifo_phys;
  70        dcr_host_t dcr_host;
  71        u32 read_offset;
  72#ifdef DEBUG
  73        u32 __iomem *trigger;
  74#endif
  75};
  76
  77#ifdef DEBUG
  78void axon_msi_debug_setup(struct device_node *dn, struct axon_msic *msic);
  79#else
  80static inline void axon_msi_debug_setup(struct device_node *dn,
  81                                        struct axon_msic *msic) { }
  82#endif
  83
  84
  85static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
  86{
  87        pr_devel("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
  88
  89        dcr_write(msic->dcr_host, dcr_n, val);
  90}
  91
  92static void axon_msi_cascade(struct irq_desc *desc)
  93{
  94        struct irq_chip *chip = irq_desc_get_chip(desc);
  95        struct axon_msic *msic = irq_desc_get_handler_data(desc);
  96        u32 write_offset, msi;
  97        int idx;
  98        int retry = 0;
  99
 100        write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG);
 101        pr_devel("axon_msi: original write_offset 0x%x\n", write_offset);
 102
 103        /* write_offset doesn't wrap properly, so we have to mask it */
 104        write_offset &= MSIC_FIFO_SIZE_MASK;
 105
 106        while (msic->read_offset != write_offset && retry < 100) {
 107                idx  = msic->read_offset / sizeof(__le32);
 108                msi  = le32_to_cpu(msic->fifo_virt[idx]);
 109                msi &= 0xFFFF;
 110
 111                pr_devel("axon_msi: woff %x roff %x msi %x\n",
 112                          write_offset, msic->read_offset, msi);
 113
 114                if (msi < nr_irqs && irq_get_chip_data(msi) == msic) {
 115                        generic_handle_irq(msi);
 116                        msic->fifo_virt[idx] = cpu_to_le32(0xffffffff);
 117                } else {
 118                        /*
 119                         * Reading the MSIC_WRITE_OFFSET_REG does not
 120                         * reliably flush the outstanding DMA to the
 121                         * FIFO buffer. Here we were reading stale
 122                         * data, so we need to retry.
 123                         */
 124                        udelay(1);
 125                        retry++;
 126                        pr_devel("axon_msi: invalid irq 0x%x!\n", msi);
 127                        continue;
 128                }
 129
 130                if (retry) {
 131                        pr_devel("axon_msi: late irq 0x%x, retry %d\n",
 132                                 msi, retry);
 133                        retry = 0;
 134                }
 135
 136                msic->read_offset += MSIC_FIFO_ENTRY_SIZE;
 137                msic->read_offset &= MSIC_FIFO_SIZE_MASK;
 138        }
 139
 140        if (retry) {
 141                printk(KERN_WARNING "axon_msi: irq timed out\n");
 142
 143                msic->read_offset += MSIC_FIFO_ENTRY_SIZE;
 144                msic->read_offset &= MSIC_FIFO_SIZE_MASK;
 145        }
 146
 147        chip->irq_eoi(&desc->irq_data);
 148}
 149
 150static struct axon_msic *find_msi_translator(struct pci_dev *dev)
 151{
 152        struct irq_domain *irq_domain;
 153        struct device_node *dn, *tmp;
 154        const phandle *ph;
 155        struct axon_msic *msic = NULL;
 156
 157        dn = of_node_get(pci_device_to_OF_node(dev));
 158        if (!dn) {
 159                dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n");
 160                return NULL;
 161        }
 162
 163        for (; dn; dn = of_get_next_parent(dn)) {
 164                ph = of_get_property(dn, "msi-translator", NULL);
 165                if (ph)
 166                        break;
 167        }
 168
 169        if (!ph) {
 170                dev_dbg(&dev->dev,
 171                        "axon_msi: no msi-translator property found\n");
 172                goto out_error;
 173        }
 174
 175        tmp = dn;
 176        dn = of_find_node_by_phandle(*ph);
 177        of_node_put(tmp);
 178        if (!dn) {
 179                dev_dbg(&dev->dev,
 180                        "axon_msi: msi-translator doesn't point to a node\n");
 181                goto out_error;
 182        }
 183
 184        irq_domain = irq_find_host(dn);
 185        if (!irq_domain) {
 186                dev_dbg(&dev->dev, "axon_msi: no irq_domain found for node %pOF\n",
 187                        dn);
 188                goto out_error;
 189        }
 190
 191        msic = irq_domain->host_data;
 192
 193out_error:
 194        of_node_put(dn);
 195
 196        return msic;
 197}
 198
 199static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
 200{
 201        struct device_node *dn;
 202        struct msi_desc *entry;
 203        int len;
 204        const u32 *prop;
 205
 206        dn = of_node_get(pci_device_to_OF_node(dev));
 207        if (!dn) {
 208                dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n");
 209                return -ENODEV;
 210        }
 211
 212        entry = first_pci_msi_entry(dev);
 213
 214        for (; dn; dn = of_get_next_parent(dn)) {
 215                if (entry->msi_attrib.is_64) {
 216                        prop = of_get_property(dn, "msi-address-64", &len);
 217                        if (prop)
 218                                break;
 219                }
 220
 221                prop = of_get_property(dn, "msi-address-32", &len);
 222                if (prop)
 223                        break;
 224        }
 225
 226        if (!prop) {
 227                dev_dbg(&dev->dev,
 228                        "axon_msi: no msi-address-(32|64) properties found\n");
 229                return -ENOENT;
 230        }
 231
 232        switch (len) {
 233        case 8:
 234                msg->address_hi = prop[0];
 235                msg->address_lo = prop[1];
 236                break;
 237        case 4:
 238                msg->address_hi = 0;
 239                msg->address_lo = prop[0];
 240                break;
 241        default:
 242                dev_dbg(&dev->dev,
 243                        "axon_msi: malformed msi-address-(32|64) property\n");
 244                of_node_put(dn);
 245                return -EINVAL;
 246        }
 247
 248        of_node_put(dn);
 249
 250        return 0;
 251}
 252
 253static int axon_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 254{
 255        unsigned int virq, rc;
 256        struct msi_desc *entry;
 257        struct msi_msg msg;
 258        struct axon_msic *msic;
 259
 260        msic = find_msi_translator(dev);
 261        if (!msic)
 262                return -ENODEV;
 263
 264        rc = setup_msi_msg_address(dev, &msg);
 265        if (rc)
 266                return rc;
 267
 268        for_each_pci_msi_entry(entry, dev) {
 269                virq = irq_create_direct_mapping(msic->irq_domain);
 270                if (!virq) {
 271                        dev_warn(&dev->dev,
 272                                 "axon_msi: virq allocation failed!\n");
 273                        return -1;
 274                }
 275                dev_dbg(&dev->dev, "axon_msi: allocated virq 0x%x\n", virq);
 276
 277                irq_set_msi_desc(virq, entry);
 278                msg.data = virq;
 279                pci_write_msi_msg(virq, &msg);
 280        }
 281
 282        return 0;
 283}
 284
 285static void axon_msi_teardown_msi_irqs(struct pci_dev *dev)
 286{
 287        struct msi_desc *entry;
 288
 289        dev_dbg(&dev->dev, "axon_msi: tearing down msi irqs\n");
 290
 291        for_each_pci_msi_entry(entry, dev) {
 292                if (!entry->irq)
 293                        continue;
 294
 295                irq_set_msi_desc(entry->irq, NULL);
 296                irq_dispose_mapping(entry->irq);
 297        }
 298}
 299
 300static struct irq_chip msic_irq_chip = {
 301        .irq_mask       = pci_msi_mask_irq,
 302        .irq_unmask     = pci_msi_unmask_irq,
 303        .irq_shutdown   = pci_msi_mask_irq,
 304        .name           = "AXON-MSI",
 305};
 306
 307static int msic_host_map(struct irq_domain *h, unsigned int virq,
 308                         irq_hw_number_t hw)
 309{
 310        irq_set_chip_data(virq, h->host_data);
 311        irq_set_chip_and_handler(virq, &msic_irq_chip, handle_simple_irq);
 312
 313        return 0;
 314}
 315
 316static const struct irq_domain_ops msic_host_ops = {
 317        .map    = msic_host_map,
 318};
 319
 320static void axon_msi_shutdown(struct platform_device *device)
 321{
 322        struct axon_msic *msic = dev_get_drvdata(&device->dev);
 323        u32 tmp;
 324
 325        pr_devel("axon_msi: disabling %pOF\n",
 326                 irq_domain_get_of_node(msic->irq_domain));
 327        tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
 328        tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
 329        msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
 330}
 331
 332static int axon_msi_probe(struct platform_device *device)
 333{
 334        struct device_node *dn = device->dev.of_node;
 335        struct axon_msic *msic;
 336        unsigned int virq;
 337        int dcr_base, dcr_len;
 338
 339        pr_devel("axon_msi: setting up dn %pOF\n", dn);
 340
 341        msic = kzalloc(sizeof(*msic), GFP_KERNEL);
 342        if (!msic) {
 343                printk(KERN_ERR "axon_msi: couldn't allocate msic for %pOF\n",
 344                       dn);
 345                goto out;
 346        }
 347
 348        dcr_base = dcr_resource_start(dn, 0);
 349        dcr_len = dcr_resource_len(dn, 0);
 350
 351        if (dcr_base == 0 || dcr_len == 0) {
 352                printk(KERN_ERR
 353                       "axon_msi: couldn't parse dcr properties on %pOF\n",
 354                        dn);
 355                goto out_free_msic;
 356        }
 357
 358        msic->dcr_host = dcr_map(dn, dcr_base, dcr_len);
 359        if (!DCR_MAP_OK(msic->dcr_host)) {
 360                printk(KERN_ERR "axon_msi: dcr_map failed for %pOF\n",
 361                       dn);
 362                goto out_free_msic;
 363        }
 364
 365        msic->fifo_virt = dma_alloc_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES,
 366                                             &msic->fifo_phys, GFP_KERNEL);
 367        if (!msic->fifo_virt) {
 368                printk(KERN_ERR "axon_msi: couldn't allocate fifo for %pOF\n",
 369                       dn);
 370                goto out_free_msic;
 371        }
 372
 373        virq = irq_of_parse_and_map(dn, 0);
 374        if (!virq) {
 375                printk(KERN_ERR "axon_msi: irq parse and map failed for %pOF\n",
 376                       dn);
 377                goto out_free_fifo;
 378        }
 379        memset(msic->fifo_virt, 0xff, MSIC_FIFO_SIZE_BYTES);
 380
 381        /* We rely on being able to stash a virq in a u16, so limit irqs to < 65536 */
 382        msic->irq_domain = irq_domain_add_nomap(dn, 65536, &msic_host_ops, msic);
 383        if (!msic->irq_domain) {
 384                printk(KERN_ERR "axon_msi: couldn't allocate irq_domain for %pOF\n",
 385                       dn);
 386                goto out_free_fifo;
 387        }
 388
 389        irq_set_handler_data(virq, msic);
 390        irq_set_chained_handler(virq, axon_msi_cascade);
 391        pr_devel("axon_msi: irq 0x%x setup for axon_msi\n", virq);
 392
 393        /* Enable the MSIC hardware */
 394        msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32);
 395        msic_dcr_write(msic, MSIC_BASE_ADDR_LO_REG,
 396                                  msic->fifo_phys & 0xFFFFFFFF);
 397        msic_dcr_write(msic, MSIC_CTRL_REG,
 398                        MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE |
 399                        MSIC_CTRL_FIFO_SIZE);
 400
 401        msic->read_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG)
 402                                & MSIC_FIFO_SIZE_MASK;
 403
 404        dev_set_drvdata(&device->dev, msic);
 405
 406        cell_pci_controller_ops.setup_msi_irqs = axon_msi_setup_msi_irqs;
 407        cell_pci_controller_ops.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
 408
 409        axon_msi_debug_setup(dn, msic);
 410
 411        printk(KERN_DEBUG "axon_msi: setup MSIC on %pOF\n", dn);
 412
 413        return 0;
 414
 415out_free_fifo:
 416        dma_free_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, msic->fifo_virt,
 417                          msic->fifo_phys);
 418out_free_msic:
 419        kfree(msic);
 420out:
 421
 422        return -1;
 423}
 424
 425static const struct of_device_id axon_msi_device_id[] = {
 426        {
 427                .compatible     = "ibm,axon-msic"
 428        },
 429        {}
 430};
 431
 432static struct platform_driver axon_msi_driver = {
 433        .probe          = axon_msi_probe,
 434        .shutdown       = axon_msi_shutdown,
 435        .driver = {
 436                .name = "axon-msi",
 437                .of_match_table = axon_msi_device_id,
 438        },
 439};
 440
 441static int __init axon_msi_init(void)
 442{
 443        return platform_driver_register(&axon_msi_driver);
 444}
 445subsys_initcall(axon_msi_init);
 446
 447
 448#ifdef DEBUG
 449static int msic_set(void *data, u64 val)
 450{
 451        struct axon_msic *msic = data;
 452        out_le32(msic->trigger, val);
 453        return 0;
 454}
 455
 456static int msic_get(void *data, u64 *val)
 457{
 458        *val = 0;
 459        return 0;
 460}
 461
 462DEFINE_SIMPLE_ATTRIBUTE(fops_msic, msic_get, msic_set, "%llu\n");
 463
 464void axon_msi_debug_setup(struct device_node *dn, struct axon_msic *msic)
 465{
 466        char name[8];
 467        u64 addr;
 468
 469        addr = of_translate_address(dn, of_get_property(dn, "reg", NULL));
 470        if (addr == OF_BAD_ADDR) {
 471                pr_devel("axon_msi: couldn't translate reg property\n");
 472                return;
 473        }
 474
 475        msic->trigger = ioremap(addr, 0x4);
 476        if (!msic->trigger) {
 477                pr_devel("axon_msi: ioremap failed\n");
 478                return;
 479        }
 480
 481        snprintf(name, sizeof(name), "msic_%d", of_node_to_nid(dn));
 482
 483        debugfs_create_file(name, 0600, powerpc_debugfs_root, msic, &fops_msic);
 484}
 485#endif /* DEBUG */
 486