0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/list.h>
0010 #include <linux/of_address.h>
0011 #include <linux/of_irq.h>
0012 #include <linux/of_platform.h>
0013 #include <linux/errno.h>
0014 #include <linux/err.h>
0015 #include <linux/export.h>
0016 #include <linux/slab.h>
0017 #include <asm/hw_irq.h>
0018 #include <asm/ppc-pci.h>
0019 #include <asm/mpic_msgr.h>
0020
0021 #define MPIC_MSGR_REGISTERS_PER_BLOCK 4
0022 #define MPIC_MSGR_STRIDE 0x10
0023 #define MPIC_MSGR_MER_OFFSET 0x100
0024 #define MSGR_INUSE 0
0025 #define MSGR_FREE 1
0026
0027 static struct mpic_msgr **mpic_msgrs;
0028 static unsigned int mpic_msgr_count;
0029 static DEFINE_RAW_SPINLOCK(msgrs_lock);
0030
0031 static inline void _mpic_msgr_mer_write(struct mpic_msgr *msgr, u32 value)
0032 {
0033 out_be32(msgr->mer, value);
0034 }
0035
0036 static inline u32 _mpic_msgr_mer_read(struct mpic_msgr *msgr)
0037 {
0038 return in_be32(msgr->mer);
0039 }
0040
0041 static inline void _mpic_msgr_disable(struct mpic_msgr *msgr)
0042 {
0043 u32 mer = _mpic_msgr_mer_read(msgr);
0044
0045 _mpic_msgr_mer_write(msgr, mer & ~(1 << msgr->num));
0046 }
0047
0048 struct mpic_msgr *mpic_msgr_get(unsigned int reg_num)
0049 {
0050 unsigned long flags;
0051 struct mpic_msgr *msgr;
0052
0053
0054 msgr = ERR_PTR(-EBUSY);
0055
0056 if (reg_num >= mpic_msgr_count)
0057 return ERR_PTR(-ENODEV);
0058
0059 raw_spin_lock_irqsave(&msgrs_lock, flags);
0060 msgr = mpic_msgrs[reg_num];
0061 if (msgr->in_use == MSGR_FREE)
0062 msgr->in_use = MSGR_INUSE;
0063 raw_spin_unlock_irqrestore(&msgrs_lock, flags);
0064
0065 return msgr;
0066 }
0067 EXPORT_SYMBOL_GPL(mpic_msgr_get);
0068
0069 void mpic_msgr_put(struct mpic_msgr *msgr)
0070 {
0071 unsigned long flags;
0072
0073 raw_spin_lock_irqsave(&msgr->lock, flags);
0074 msgr->in_use = MSGR_FREE;
0075 _mpic_msgr_disable(msgr);
0076 raw_spin_unlock_irqrestore(&msgr->lock, flags);
0077 }
0078 EXPORT_SYMBOL_GPL(mpic_msgr_put);
0079
0080 void mpic_msgr_enable(struct mpic_msgr *msgr)
0081 {
0082 unsigned long flags;
0083 u32 mer;
0084
0085 raw_spin_lock_irqsave(&msgr->lock, flags);
0086 mer = _mpic_msgr_mer_read(msgr);
0087 _mpic_msgr_mer_write(msgr, mer | (1 << msgr->num));
0088 raw_spin_unlock_irqrestore(&msgr->lock, flags);
0089 }
0090 EXPORT_SYMBOL_GPL(mpic_msgr_enable);
0091
0092 void mpic_msgr_disable(struct mpic_msgr *msgr)
0093 {
0094 unsigned long flags;
0095
0096 raw_spin_lock_irqsave(&msgr->lock, flags);
0097 _mpic_msgr_disable(msgr);
0098 raw_spin_unlock_irqrestore(&msgr->lock, flags);
0099 }
0100 EXPORT_SYMBOL_GPL(mpic_msgr_disable);
0101
0102
0103
0104
0105
0106 static unsigned int mpic_msgr_number_of_blocks(void)
0107 {
0108 unsigned int count;
0109 struct device_node *aliases;
0110
0111 count = 0;
0112 aliases = of_find_node_by_name(NULL, "aliases");
0113
0114 if (aliases) {
0115 char buf[32];
0116
0117 for (;;) {
0118 snprintf(buf, sizeof(buf), "mpic-msgr-block%d", count);
0119 if (!of_find_property(aliases, buf, NULL))
0120 break;
0121
0122 count += 1;
0123 }
0124 }
0125
0126 return count;
0127 }
0128
0129 static unsigned int mpic_msgr_number_of_registers(void)
0130 {
0131 return mpic_msgr_number_of_blocks() * MPIC_MSGR_REGISTERS_PER_BLOCK;
0132 }
0133
0134 static int mpic_msgr_block_number(struct device_node *node)
0135 {
0136 struct device_node *aliases;
0137 unsigned int index, number_of_blocks;
0138 char buf[64];
0139
0140 number_of_blocks = mpic_msgr_number_of_blocks();
0141 aliases = of_find_node_by_name(NULL, "aliases");
0142 if (!aliases)
0143 return -1;
0144
0145 for (index = 0; index < number_of_blocks; ++index) {
0146 struct property *prop;
0147
0148 snprintf(buf, sizeof(buf), "mpic-msgr-block%d", index);
0149 prop = of_find_property(aliases, buf, NULL);
0150 if (node == of_find_node_by_path(prop->value))
0151 break;
0152 }
0153
0154 return index == number_of_blocks ? -1 : index;
0155 }
0156
0157
0158
0159 static int mpic_msgr_probe(struct platform_device *dev)
0160 {
0161 void __iomem *msgr_block_addr;
0162 int block_number;
0163 struct resource rsrc;
0164 unsigned int i;
0165 unsigned int irq_index;
0166 struct device_node *np = dev->dev.of_node;
0167 unsigned int receive_mask;
0168 const unsigned int *prop;
0169
0170 if (!np) {
0171 dev_err(&dev->dev, "Device OF-Node is NULL");
0172 return -EFAULT;
0173 }
0174
0175
0176
0177
0178 if (!mpic_msgrs) {
0179 mpic_msgr_count = mpic_msgr_number_of_registers();
0180 dev_info(&dev->dev, "Found %d message registers\n",
0181 mpic_msgr_count);
0182
0183 mpic_msgrs = kcalloc(mpic_msgr_count, sizeof(*mpic_msgrs),
0184 GFP_KERNEL);
0185 if (!mpic_msgrs) {
0186 dev_err(&dev->dev,
0187 "No memory for message register blocks\n");
0188 return -ENOMEM;
0189 }
0190 }
0191 dev_info(&dev->dev, "Of-device full name %pOF\n", np);
0192
0193
0194 of_address_to_resource(np, 0, &rsrc);
0195 msgr_block_addr = devm_ioremap(&dev->dev, rsrc.start, resource_size(&rsrc));
0196 if (!msgr_block_addr) {
0197 dev_err(&dev->dev, "Failed to iomap MPIC message registers");
0198 return -EFAULT;
0199 }
0200
0201
0202 block_number = mpic_msgr_block_number(np);
0203 if (block_number < 0) {
0204 dev_err(&dev->dev,
0205 "Failed to find message register block alias\n");
0206 return -ENODEV;
0207 }
0208 dev_info(&dev->dev, "Setting up message register block %d\n",
0209 block_number);
0210
0211
0212
0213
0214 prop = of_get_property(np, "mpic-msgr-receive-mask", NULL);
0215 receive_mask = (prop) ? *prop : 0xF;
0216
0217
0218 for (i = 0, irq_index = 0; i < MPIC_MSGR_REGISTERS_PER_BLOCK; ++i) {
0219 struct mpic_msgr *msgr;
0220 unsigned int reg_number;
0221
0222 msgr = kzalloc(sizeof(struct mpic_msgr), GFP_KERNEL);
0223 if (!msgr) {
0224 dev_err(&dev->dev, "No memory for message register\n");
0225 return -ENOMEM;
0226 }
0227
0228 reg_number = block_number * MPIC_MSGR_REGISTERS_PER_BLOCK + i;
0229 msgr->base = msgr_block_addr + i * MPIC_MSGR_STRIDE;
0230 msgr->mer = (u32 *)((u8 *)msgr->base + MPIC_MSGR_MER_OFFSET);
0231 msgr->in_use = MSGR_FREE;
0232 msgr->num = i;
0233 raw_spin_lock_init(&msgr->lock);
0234
0235 if (receive_mask & (1 << i)) {
0236 msgr->irq = irq_of_parse_and_map(np, irq_index);
0237 if (!msgr->irq) {
0238 dev_err(&dev->dev,
0239 "Missing interrupt specifier");
0240 kfree(msgr);
0241 return -EFAULT;
0242 }
0243 irq_index += 1;
0244 } else {
0245 msgr->irq = 0;
0246 }
0247
0248 mpic_msgrs[reg_number] = msgr;
0249 mpic_msgr_disable(msgr);
0250 dev_info(&dev->dev, "Register %d initialized: irq %d\n",
0251 reg_number, msgr->irq);
0252
0253 }
0254
0255 return 0;
0256 }
0257
0258 static const struct of_device_id mpic_msgr_ids[] = {
0259 {
0260 .compatible = "fsl,mpic-v3.1-msgr",
0261 .data = NULL,
0262 },
0263 {}
0264 };
0265
0266 static struct platform_driver mpic_msgr_driver = {
0267 .driver = {
0268 .name = "mpic-msgr",
0269 .of_match_table = mpic_msgr_ids,
0270 },
0271 .probe = mpic_msgr_probe,
0272 };
0273
0274 static __init int mpic_msgr_init(void)
0275 {
0276 return platform_driver_register(&mpic_msgr_driver);
0277 }
0278 subsys_initcall(mpic_msgr_init);