root/arch/powerpc/sysdev/mpic_msgr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _mpic_msgr_mer_write
  2. _mpic_msgr_mer_read
  3. _mpic_msgr_disable
  4. mpic_msgr_get
  5. mpic_msgr_put
  6. mpic_msgr_enable
  7. mpic_msgr_disable
  8. mpic_msgr_number_of_blocks
  9. mpic_msgr_number_of_registers
  10. mpic_msgr_block_number
  11. mpic_msgr_probe
  12. mpic_msgr_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright 2011-2012, Meador Inge, Mentor Graphics Corporation.
   4  *
   5  * Some ideas based on un-pushed work done by Vivek Mahajan, Jason Jin, and
   6  * Mingkai Hu from Freescale Semiconductor, Inc.
   7  */
   8 
   9 #include <linux/list.h>
  10 #include <linux/of_platform.h>
  11 #include <linux/errno.h>
  12 #include <linux/err.h>
  13 #include <linux/export.h>
  14 #include <linux/slab.h>
  15 #include <asm/prom.h>
  16 #include <asm/hw_irq.h>
  17 #include <asm/ppc-pci.h>
  18 #include <asm/mpic_msgr.h>
  19 
  20 #define MPIC_MSGR_REGISTERS_PER_BLOCK   4
  21 #define MPIC_MSGR_STRIDE                0x10
  22 #define MPIC_MSGR_MER_OFFSET            0x100
  23 #define MSGR_INUSE                      0
  24 #define MSGR_FREE                       1
  25 
  26 static struct mpic_msgr **mpic_msgrs;
  27 static unsigned int mpic_msgr_count;
  28 static DEFINE_RAW_SPINLOCK(msgrs_lock);
  29 
  30 static inline void _mpic_msgr_mer_write(struct mpic_msgr *msgr, u32 value)
  31 {
  32         out_be32(msgr->mer, value);
  33 }
  34 
  35 static inline u32 _mpic_msgr_mer_read(struct mpic_msgr *msgr)
  36 {
  37         return in_be32(msgr->mer);
  38 }
  39 
  40 static inline void _mpic_msgr_disable(struct mpic_msgr *msgr)
  41 {
  42         u32 mer = _mpic_msgr_mer_read(msgr);
  43 
  44         _mpic_msgr_mer_write(msgr, mer & ~(1 << msgr->num));
  45 }
  46 
  47 struct mpic_msgr *mpic_msgr_get(unsigned int reg_num)
  48 {
  49         unsigned long flags;
  50         struct mpic_msgr *msgr;
  51 
  52         /* Assume busy until proven otherwise.  */
  53         msgr = ERR_PTR(-EBUSY);
  54 
  55         if (reg_num >= mpic_msgr_count)
  56                 return ERR_PTR(-ENODEV);
  57 
  58         raw_spin_lock_irqsave(&msgrs_lock, flags);
  59         msgr = mpic_msgrs[reg_num];
  60         if (msgr->in_use == MSGR_FREE)
  61                 msgr->in_use = MSGR_INUSE;
  62         raw_spin_unlock_irqrestore(&msgrs_lock, flags);
  63 
  64         return msgr;
  65 }
  66 EXPORT_SYMBOL_GPL(mpic_msgr_get);
  67 
  68 void mpic_msgr_put(struct mpic_msgr *msgr)
  69 {
  70         unsigned long flags;
  71 
  72         raw_spin_lock_irqsave(&msgr->lock, flags);
  73         msgr->in_use = MSGR_FREE;
  74         _mpic_msgr_disable(msgr);
  75         raw_spin_unlock_irqrestore(&msgr->lock, flags);
  76 }
  77 EXPORT_SYMBOL_GPL(mpic_msgr_put);
  78 
  79 void mpic_msgr_enable(struct mpic_msgr *msgr)
  80 {
  81         unsigned long flags;
  82         u32 mer;
  83 
  84         raw_spin_lock_irqsave(&msgr->lock, flags);
  85         mer = _mpic_msgr_mer_read(msgr);
  86         _mpic_msgr_mer_write(msgr, mer | (1 << msgr->num));
  87         raw_spin_unlock_irqrestore(&msgr->lock, flags);
  88 }
  89 EXPORT_SYMBOL_GPL(mpic_msgr_enable);
  90 
  91 void mpic_msgr_disable(struct mpic_msgr *msgr)
  92 {
  93         unsigned long flags;
  94 
  95         raw_spin_lock_irqsave(&msgr->lock, flags);
  96         _mpic_msgr_disable(msgr);
  97         raw_spin_unlock_irqrestore(&msgr->lock, flags);
  98 }
  99 EXPORT_SYMBOL_GPL(mpic_msgr_disable);
 100 
 101 /* The following three functions are used to compute the order and number of
 102  * the message register blocks.  They are clearly very inefficent.  However,
 103  * they are called *only* a few times during device initialization.
 104  */
 105 static unsigned int mpic_msgr_number_of_blocks(void)
 106 {
 107         unsigned int count;
 108         struct device_node *aliases;
 109 
 110         count = 0;
 111         aliases = of_find_node_by_name(NULL, "aliases");
 112 
 113         if (aliases) {
 114                 char buf[32];
 115 
 116                 for (;;) {
 117                         snprintf(buf, sizeof(buf), "mpic-msgr-block%d", count);
 118                         if (!of_find_property(aliases, buf, NULL))
 119                                 break;
 120 
 121                         count += 1;
 122                 }
 123         }
 124 
 125         return count;
 126 }
 127 
 128 static unsigned int mpic_msgr_number_of_registers(void)
 129 {
 130         return mpic_msgr_number_of_blocks() * MPIC_MSGR_REGISTERS_PER_BLOCK;
 131 }
 132 
 133 static int mpic_msgr_block_number(struct device_node *node)
 134 {
 135         struct device_node *aliases;
 136         unsigned int index, number_of_blocks;
 137         char buf[64];
 138 
 139         number_of_blocks = mpic_msgr_number_of_blocks();
 140         aliases = of_find_node_by_name(NULL, "aliases");
 141         if (!aliases)
 142                 return -1;
 143 
 144         for (index = 0; index < number_of_blocks; ++index) {
 145                 struct property *prop;
 146 
 147                 snprintf(buf, sizeof(buf), "mpic-msgr-block%d", index);
 148                 prop = of_find_property(aliases, buf, NULL);
 149                 if (node == of_find_node_by_path(prop->value))
 150                         break;
 151         }
 152 
 153         return index == number_of_blocks ? -1 : index;
 154 }
 155 
 156 /* The probe function for a single message register block.
 157  */
 158 static int mpic_msgr_probe(struct platform_device *dev)
 159 {
 160         void __iomem *msgr_block_addr;
 161         int block_number;
 162         struct resource rsrc;
 163         unsigned int i;
 164         unsigned int irq_index;
 165         struct device_node *np = dev->dev.of_node;
 166         unsigned int receive_mask;
 167         const unsigned int *prop;
 168 
 169         if (!np) {
 170                 dev_err(&dev->dev, "Device OF-Node is NULL");
 171                 return -EFAULT;
 172         }
 173 
 174         /* Allocate the message register array upon the first device
 175          * registered.
 176          */
 177         if (!mpic_msgrs) {
 178                 mpic_msgr_count = mpic_msgr_number_of_registers();
 179                 dev_info(&dev->dev, "Found %d message registers\n",
 180                                 mpic_msgr_count);
 181 
 182                 mpic_msgrs = kcalloc(mpic_msgr_count, sizeof(*mpic_msgrs),
 183                                                          GFP_KERNEL);
 184                 if (!mpic_msgrs) {
 185                         dev_err(&dev->dev,
 186                                 "No memory for message register blocks\n");
 187                         return -ENOMEM;
 188                 }
 189         }
 190         dev_info(&dev->dev, "Of-device full name %pOF\n", np);
 191 
 192         /* IO map the message register block. */
 193         of_address_to_resource(np, 0, &rsrc);
 194         msgr_block_addr = ioremap(rsrc.start, resource_size(&rsrc));
 195         if (!msgr_block_addr) {
 196                 dev_err(&dev->dev, "Failed to iomap MPIC message registers");
 197                 return -EFAULT;
 198         }
 199 
 200         /* Ensure the block has a defined order. */
 201         block_number = mpic_msgr_block_number(np);
 202         if (block_number < 0) {
 203                 dev_err(&dev->dev,
 204                         "Failed to find message register block alias\n");
 205                 return -ENODEV;
 206         }
 207         dev_info(&dev->dev, "Setting up message register block %d\n",
 208                         block_number);
 209 
 210         /* Grab the receive mask which specifies what registers can receive
 211          * interrupts.
 212          */
 213         prop = of_get_property(np, "mpic-msgr-receive-mask", NULL);
 214         receive_mask = (prop) ? *prop : 0xF;
 215 
 216         /* Build up the appropriate message register data structures. */
 217         for (i = 0, irq_index = 0; i < MPIC_MSGR_REGISTERS_PER_BLOCK; ++i) {
 218                 struct mpic_msgr *msgr;
 219                 unsigned int reg_number;
 220 
 221                 msgr = kzalloc(sizeof(struct mpic_msgr), GFP_KERNEL);
 222                 if (!msgr) {
 223                         dev_err(&dev->dev, "No memory for message register\n");
 224                         return -ENOMEM;
 225                 }
 226 
 227                 reg_number = block_number * MPIC_MSGR_REGISTERS_PER_BLOCK + i;
 228                 msgr->base = msgr_block_addr + i * MPIC_MSGR_STRIDE;
 229                 msgr->mer = (u32 *)((u8 *)msgr->base + MPIC_MSGR_MER_OFFSET);
 230                 msgr->in_use = MSGR_FREE;
 231                 msgr->num = i;
 232                 raw_spin_lock_init(&msgr->lock);
 233 
 234                 if (receive_mask & (1 << i)) {
 235                         msgr->irq = irq_of_parse_and_map(np, irq_index);
 236                         if (!msgr->irq) {
 237                                 dev_err(&dev->dev,
 238                                                 "Missing interrupt specifier");
 239                                 kfree(msgr);
 240                                 return -EFAULT;
 241                         }
 242                         irq_index += 1;
 243                 } else {
 244                         msgr->irq = 0;
 245                 }
 246 
 247                 mpic_msgrs[reg_number] = msgr;
 248                 mpic_msgr_disable(msgr);
 249                 dev_info(&dev->dev, "Register %d initialized: irq %d\n",
 250                                 reg_number, msgr->irq);
 251 
 252         }
 253 
 254         return 0;
 255 }
 256 
 257 static const struct of_device_id mpic_msgr_ids[] = {
 258         {
 259                 .compatible = "fsl,mpic-v3.1-msgr",
 260                 .data = NULL,
 261         },
 262         {}
 263 };
 264 
 265 static struct platform_driver mpic_msgr_driver = {
 266         .driver = {
 267                 .name = "mpic-msgr",
 268                 .of_match_table = mpic_msgr_ids,
 269         },
 270         .probe = mpic_msgr_probe,
 271 };
 272 
 273 static __init int mpic_msgr_init(void)
 274 {
 275         return platform_driver_register(&mpic_msgr_driver);
 276 }
 277 subsys_initcall(mpic_msgr_init);

/* [<][>][^][v][top][bottom][index][help] */