0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/init.h>
0010 #include <linux/msi.h>
0011 #include <linux/spinlock.h>
0012 #include <linux/interrupt.h>
0013
0014 #include <asm/octeon/octeon.h>
0015 #include <asm/octeon/cvmx-npi-defs.h>
0016 #include <asm/octeon/cvmx-pci-defs.h>
0017 #include <asm/octeon/cvmx-npei-defs.h>
0018 #include <asm/octeon/cvmx-sli-defs.h>
0019 #include <asm/octeon/cvmx-pexp-defs.h>
0020 #include <asm/octeon/pci-octeon.h>
0021
0022
0023
0024
0025
0026 static u64 msi_free_irq_bitmask[4];
0027
0028
0029
0030
0031
0032
0033
0034 static u64 msi_multiple_irq_bitmask[4];
0035
0036
0037
0038
0039
0040 static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock);
0041
0042
0043
0044
0045
0046 static int msi_irq_size;
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
0062 {
0063 struct msi_msg msg;
0064 u16 control;
0065 int configured_private_bits;
0066 int request_private_bits;
0067 int irq = 0;
0068 int irq_step;
0069 u64 search_mask;
0070 int index;
0071
0072 if (desc->pci.msi_attrib.is_msix)
0073 return -EINVAL;
0074
0075
0076
0077
0078
0079
0080 pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
0081
0082
0083
0084
0085
0086
0087
0088 configured_private_bits = (control & PCI_MSI_FLAGS_QSIZE) >> 4;
0089 if (configured_private_bits == 0) {
0090
0091 request_private_bits = (control & PCI_MSI_FLAGS_QMASK) >> 1;
0092 } else {
0093
0094
0095
0096
0097
0098 request_private_bits = configured_private_bits;
0099 }
0100
0101
0102
0103
0104
0105 if (request_private_bits > 5)
0106 request_private_bits = 0;
0107
0108 try_only_one:
0109
0110
0111
0112
0113 irq_step = 1 << request_private_bits;
0114
0115
0116 search_mask = (1 << irq_step) - 1;
0117
0118
0119
0120
0121
0122
0123 spin_lock(&msi_free_irq_bitmask_lock);
0124 for (index = 0; index < msi_irq_size/64; index++) {
0125 for (irq = 0; irq < 64; irq += irq_step) {
0126 if ((msi_free_irq_bitmask[index] & (search_mask << irq)) == 0) {
0127 msi_free_irq_bitmask[index] |= search_mask << irq;
0128 msi_multiple_irq_bitmask[index] |= (search_mask >> 1) << irq;
0129 goto msi_irq_allocated;
0130 }
0131 }
0132 }
0133 msi_irq_allocated:
0134 spin_unlock(&msi_free_irq_bitmask_lock);
0135
0136
0137 if (irq >= 64) {
0138 if (request_private_bits) {
0139 pr_err("arch_setup_msi_irq: Unable to find %d free interrupts, trying just one",
0140 1 << request_private_bits);
0141 request_private_bits = 0;
0142 goto try_only_one;
0143 } else
0144 panic("arch_setup_msi_irq: Unable to find a free MSI interrupt");
0145 }
0146
0147
0148 irq += index*64;
0149 irq += OCTEON_IRQ_MSI_BIT0;
0150
0151 switch (octeon_dma_bar_type) {
0152 case OCTEON_DMA_BAR_TYPE_SMALL:
0153
0154 msg.address_lo =
0155 ((128ul << 20) + CVMX_PCI_MSI_RCV) & 0xffffffff;
0156 msg.address_hi = ((128ul << 20) + CVMX_PCI_MSI_RCV) >> 32;
0157 break;
0158 case OCTEON_DMA_BAR_TYPE_BIG:
0159
0160 msg.address_lo = (0 + CVMX_PCI_MSI_RCV) & 0xffffffff;
0161 msg.address_hi = (0 + CVMX_PCI_MSI_RCV) >> 32;
0162 break;
0163 case OCTEON_DMA_BAR_TYPE_PCIE:
0164
0165
0166 msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff;
0167 msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32;
0168 break;
0169 case OCTEON_DMA_BAR_TYPE_PCIE2:
0170
0171 msg.address_lo = (0 + CVMX_SLI_PCIE_MSI_RCV) & 0xffffffff;
0172 msg.address_hi = (0 + CVMX_SLI_PCIE_MSI_RCV) >> 32;
0173 break;
0174 default:
0175 panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type");
0176 }
0177 msg.data = irq - OCTEON_IRQ_MSI_BIT0;
0178
0179
0180 control &= ~PCI_MSI_FLAGS_QSIZE;
0181 control |= request_private_bits << 4;
0182 pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
0183
0184 irq_set_msi_desc(irq, desc);
0185 pci_write_msi_msg(irq, &msg);
0186 return 0;
0187 }
0188
0189
0190
0191
0192
0193
0194
0195
0196 void arch_teardown_msi_irq(unsigned int irq)
0197 {
0198 int number_irqs;
0199 u64 bitmask;
0200 int index = 0;
0201 int irq0;
0202
0203 if ((irq < OCTEON_IRQ_MSI_BIT0)
0204 || (irq > msi_irq_size + OCTEON_IRQ_MSI_BIT0))
0205 panic("arch_teardown_msi_irq: Attempted to teardown illegal "
0206 "MSI interrupt (%d)", irq);
0207
0208 irq -= OCTEON_IRQ_MSI_BIT0;
0209 index = irq / 64;
0210 irq0 = irq % 64;
0211
0212
0213
0214
0215
0216
0217 number_irqs = 0;
0218 while ((irq0 + number_irqs < 64) &&
0219 (msi_multiple_irq_bitmask[index]
0220 & (1ull << (irq0 + number_irqs))))
0221 number_irqs++;
0222 number_irqs++;
0223
0224 bitmask = (1 << number_irqs) - 1;
0225
0226 bitmask <<= irq0;
0227 if ((msi_free_irq_bitmask[index] & bitmask) != bitmask)
0228 panic("arch_teardown_msi_irq: Attempted to teardown MSI "
0229 "interrupt (%d) not in use", irq);
0230
0231
0232 spin_lock(&msi_free_irq_bitmask_lock);
0233 msi_free_irq_bitmask[index] &= ~bitmask;
0234 msi_multiple_irq_bitmask[index] &= ~bitmask;
0235 spin_unlock(&msi_free_irq_bitmask_lock);
0236 }
0237
0238 static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock);
0239
0240 static u64 msi_rcv_reg[4];
0241 static u64 mis_ena_reg[4];
0242
0243 static void octeon_irq_msi_enable_pcie(struct irq_data *data)
0244 {
0245 u64 en;
0246 unsigned long flags;
0247 int msi_number = data->irq - OCTEON_IRQ_MSI_BIT0;
0248 int irq_index = msi_number >> 6;
0249 int irq_bit = msi_number & 0x3f;
0250
0251 raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags);
0252 en = cvmx_read_csr(mis_ena_reg[irq_index]);
0253 en |= 1ull << irq_bit;
0254 cvmx_write_csr(mis_ena_reg[irq_index], en);
0255 cvmx_read_csr(mis_ena_reg[irq_index]);
0256 raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags);
0257 }
0258
0259 static void octeon_irq_msi_disable_pcie(struct irq_data *data)
0260 {
0261 u64 en;
0262 unsigned long flags;
0263 int msi_number = data->irq - OCTEON_IRQ_MSI_BIT0;
0264 int irq_index = msi_number >> 6;
0265 int irq_bit = msi_number & 0x3f;
0266
0267 raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags);
0268 en = cvmx_read_csr(mis_ena_reg[irq_index]);
0269 en &= ~(1ull << irq_bit);
0270 cvmx_write_csr(mis_ena_reg[irq_index], en);
0271 cvmx_read_csr(mis_ena_reg[irq_index]);
0272 raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags);
0273 }
0274
0275 static struct irq_chip octeon_irq_chip_msi_pcie = {
0276 .name = "MSI",
0277 .irq_enable = octeon_irq_msi_enable_pcie,
0278 .irq_disable = octeon_irq_msi_disable_pcie,
0279 };
0280
0281 static void octeon_irq_msi_enable_pci(struct irq_data *data)
0282 {
0283
0284
0285
0286
0287
0288
0289
0290 }
0291
0292 static void octeon_irq_msi_disable_pci(struct irq_data *data)
0293 {
0294
0295 }
0296
0297 static struct irq_chip octeon_irq_chip_msi_pci = {
0298 .name = "MSI",
0299 .irq_enable = octeon_irq_msi_enable_pci,
0300 .irq_disable = octeon_irq_msi_disable_pci,
0301 };
0302
0303
0304
0305
0306
0307 static irqreturn_t __octeon_msi_do_interrupt(int index, u64 msi_bits)
0308 {
0309 int irq;
0310 int bit;
0311
0312 bit = fls64(msi_bits);
0313 if (bit) {
0314 bit--;
0315
0316 cvmx_write_csr(msi_rcv_reg[index], 1ull << bit);
0317
0318 irq = bit + OCTEON_IRQ_MSI_BIT0 + 64 * index;
0319 do_IRQ(irq);
0320 return IRQ_HANDLED;
0321 }
0322 return IRQ_NONE;
0323 }
0324
0325 #define OCTEON_MSI_INT_HANDLER_X(x) \
0326 static irqreturn_t octeon_msi_interrupt##x(int cpl, void *dev_id) \
0327 { \
0328 u64 msi_bits = cvmx_read_csr(msi_rcv_reg[(x)]); \
0329 return __octeon_msi_do_interrupt((x), msi_bits); \
0330 }
0331
0332
0333
0334
0335 OCTEON_MSI_INT_HANDLER_X(0);
0336 OCTEON_MSI_INT_HANDLER_X(1);
0337 OCTEON_MSI_INT_HANDLER_X(2);
0338 OCTEON_MSI_INT_HANDLER_X(3);
0339
0340
0341
0342
0343 int __init octeon_msi_initialize(void)
0344 {
0345 int irq;
0346 struct irq_chip *msi;
0347
0348 if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_INVALID) {
0349 return 0;
0350 } else if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) {
0351 msi_rcv_reg[0] = CVMX_PEXP_NPEI_MSI_RCV0;
0352 msi_rcv_reg[1] = CVMX_PEXP_NPEI_MSI_RCV1;
0353 msi_rcv_reg[2] = CVMX_PEXP_NPEI_MSI_RCV2;
0354 msi_rcv_reg[3] = CVMX_PEXP_NPEI_MSI_RCV3;
0355 mis_ena_reg[0] = CVMX_PEXP_NPEI_MSI_ENB0;
0356 mis_ena_reg[1] = CVMX_PEXP_NPEI_MSI_ENB1;
0357 mis_ena_reg[2] = CVMX_PEXP_NPEI_MSI_ENB2;
0358 mis_ena_reg[3] = CVMX_PEXP_NPEI_MSI_ENB3;
0359 msi = &octeon_irq_chip_msi_pcie;
0360 } else {
0361 msi_rcv_reg[0] = CVMX_NPI_NPI_MSI_RCV;
0362 #define INVALID_GENERATE_ADE 0x8700000000000000ULL;
0363 msi_rcv_reg[1] = INVALID_GENERATE_ADE;
0364 msi_rcv_reg[2] = INVALID_GENERATE_ADE;
0365 msi_rcv_reg[3] = INVALID_GENERATE_ADE;
0366 mis_ena_reg[0] = INVALID_GENERATE_ADE;
0367 mis_ena_reg[1] = INVALID_GENERATE_ADE;
0368 mis_ena_reg[2] = INVALID_GENERATE_ADE;
0369 mis_ena_reg[3] = INVALID_GENERATE_ADE;
0370 msi = &octeon_irq_chip_msi_pci;
0371 }
0372
0373 for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_LAST; irq++)
0374 irq_set_chip_and_handler(irq, msi, handle_simple_irq);
0375
0376 if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
0377 if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt0,
0378 0, "MSI[0:63]", octeon_msi_interrupt0))
0379 panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed");
0380
0381 if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt1,
0382 0, "MSI[64:127]", octeon_msi_interrupt1))
0383 panic("request_irq(OCTEON_IRQ_PCI_MSI1) failed");
0384
0385 if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt2,
0386 0, "MSI[127:191]", octeon_msi_interrupt2))
0387 panic("request_irq(OCTEON_IRQ_PCI_MSI2) failed");
0388
0389 if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt3,
0390 0, "MSI[192:255]", octeon_msi_interrupt3))
0391 panic("request_irq(OCTEON_IRQ_PCI_MSI3) failed");
0392
0393 msi_irq_size = 256;
0394 } else if (octeon_is_pci_host()) {
0395 if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt0,
0396 0, "MSI[0:15]", octeon_msi_interrupt0))
0397 panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed");
0398
0399 if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt0,
0400 0, "MSI[16:31]", octeon_msi_interrupt0))
0401 panic("request_irq(OCTEON_IRQ_PCI_MSI1) failed");
0402
0403 if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt0,
0404 0, "MSI[32:47]", octeon_msi_interrupt0))
0405 panic("request_irq(OCTEON_IRQ_PCI_MSI2) failed");
0406
0407 if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt0,
0408 0, "MSI[48:63]", octeon_msi_interrupt0))
0409 panic("request_irq(OCTEON_IRQ_PCI_MSI3) failed");
0410 msi_irq_size = 64;
0411 }
0412 return 0;
0413 }
0414 subsys_initcall(octeon_msi_initialize);