0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/init.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/irq.h>
0015 #include <linux/irqchip/chained_irq.h>
0016 #include <linux/irqdomain.h>
0017 #include <linux/kernel.h>
0018 #include <linux/module.h>
0019 #include <linux/msi.h>
0020 #include <linux/of_address.h>
0021 #include <linux/of_irq.h>
0022 #include <linux/of_platform.h>
0023 #include <linux/of_pci.h>
0024 #include <linux/pci.h>
0025 #include <linux/platform_device.h>
0026 #include <linux/slab.h>
0027
0028 #include "pcie-mobiveil.h"
0029
0030 static bool mobiveil_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
0031 {
0032
0033 if (pci_is_root_bus(bus) && (devfn > 0))
0034 return false;
0035
0036
0037
0038
0039
0040 if ((bus->primary == to_pci_host_bridge(bus->bridge)->busnr) && (PCI_SLOT(devfn) > 0))
0041 return false;
0042
0043 return true;
0044 }
0045
0046
0047
0048
0049
0050 static void __iomem *mobiveil_pcie_map_bus(struct pci_bus *bus,
0051 unsigned int devfn, int where)
0052 {
0053 struct mobiveil_pcie *pcie = bus->sysdata;
0054 struct mobiveil_root_port *rp = &pcie->rp;
0055 u32 value;
0056
0057 if (!mobiveil_pcie_valid_device(bus, devfn))
0058 return NULL;
0059
0060
0061 if (pci_is_root_bus(bus))
0062 return pcie->csr_axi_slave_base + where;
0063
0064
0065
0066
0067
0068
0069
0070 value = bus->number << PAB_BUS_SHIFT |
0071 PCI_SLOT(devfn) << PAB_DEVICE_SHIFT |
0072 PCI_FUNC(devfn) << PAB_FUNCTION_SHIFT;
0073
0074 mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_PEX_WIN_L(WIN_NUM_0));
0075
0076 return rp->config_axi_slave_base + where;
0077 }
0078
0079 static struct pci_ops mobiveil_pcie_ops = {
0080 .map_bus = mobiveil_pcie_map_bus,
0081 .read = pci_generic_config_read,
0082 .write = pci_generic_config_write,
0083 };
0084
0085 static void mobiveil_pcie_isr(struct irq_desc *desc)
0086 {
0087 struct irq_chip *chip = irq_desc_get_chip(desc);
0088 struct mobiveil_pcie *pcie = irq_desc_get_handler_data(desc);
0089 struct device *dev = &pcie->pdev->dev;
0090 struct mobiveil_root_port *rp = &pcie->rp;
0091 struct mobiveil_msi *msi = &rp->msi;
0092 u32 msi_data, msi_addr_lo, msi_addr_hi;
0093 u32 intr_status, msi_status;
0094 unsigned long shifted_status;
0095 u32 bit, val, mask;
0096
0097
0098
0099
0100
0101
0102 chained_irq_enter(chip, desc);
0103
0104
0105 val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_STAT);
0106 mask = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
0107 intr_status = val & mask;
0108
0109
0110 if (intr_status & PAB_INTP_INTX_MASK) {
0111 shifted_status = mobiveil_csr_readl(pcie,
0112 PAB_INTP_AMBA_MISC_STAT);
0113 shifted_status &= PAB_INTP_INTX_MASK;
0114 shifted_status >>= PAB_INTX_START;
0115 do {
0116 for_each_set_bit(bit, &shifted_status, PCI_NUM_INTX) {
0117 int ret;
0118 ret = generic_handle_domain_irq(rp->intx_domain,
0119 bit + 1);
0120 if (ret)
0121 dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n",
0122 bit);
0123
0124
0125 mobiveil_csr_writel(pcie,
0126 1 << (PAB_INTX_START + bit),
0127 PAB_INTP_AMBA_MISC_STAT);
0128 }
0129
0130 shifted_status = mobiveil_csr_readl(pcie,
0131 PAB_INTP_AMBA_MISC_STAT);
0132 shifted_status &= PAB_INTP_INTX_MASK;
0133 shifted_status >>= PAB_INTX_START;
0134 } while (shifted_status != 0);
0135 }
0136
0137
0138 msi_status = readl_relaxed(pcie->apb_csr_base + MSI_STATUS_OFFSET);
0139
0140
0141 while (msi_status & 1) {
0142 msi_data = readl_relaxed(pcie->apb_csr_base + MSI_DATA_OFFSET);
0143
0144
0145
0146
0147
0148
0149
0150 msi_addr_lo = readl_relaxed(pcie->apb_csr_base +
0151 MSI_ADDR_L_OFFSET);
0152 msi_addr_hi = readl_relaxed(pcie->apb_csr_base +
0153 MSI_ADDR_H_OFFSET);
0154 dev_dbg(dev, "MSI registers, data: %08x, addr: %08x:%08x\n",
0155 msi_data, msi_addr_hi, msi_addr_lo);
0156
0157 generic_handle_domain_irq(msi->dev_domain, msi_data);
0158
0159 msi_status = readl_relaxed(pcie->apb_csr_base +
0160 MSI_STATUS_OFFSET);
0161 }
0162
0163
0164 mobiveil_csr_writel(pcie, intr_status, PAB_INTP_AMBA_MISC_STAT);
0165 chained_irq_exit(chip, desc);
0166 }
0167
0168 static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
0169 {
0170 struct device *dev = &pcie->pdev->dev;
0171 struct platform_device *pdev = pcie->pdev;
0172 struct device_node *node = dev->of_node;
0173 struct mobiveil_root_port *rp = &pcie->rp;
0174 struct resource *res;
0175
0176
0177 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
0178 "config_axi_slave");
0179 rp->config_axi_slave_base = devm_pci_remap_cfg_resource(dev, res);
0180 if (IS_ERR(rp->config_axi_slave_base))
0181 return PTR_ERR(rp->config_axi_slave_base);
0182 rp->ob_io_res = res;
0183
0184
0185 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
0186 "csr_axi_slave");
0187 pcie->csr_axi_slave_base = devm_pci_remap_cfg_resource(dev, res);
0188 if (IS_ERR(pcie->csr_axi_slave_base))
0189 return PTR_ERR(pcie->csr_axi_slave_base);
0190 pcie->pcie_reg_base = res->start;
0191
0192
0193 if (of_property_read_u32(node, "apio-wins", &pcie->apio_wins))
0194 pcie->apio_wins = MAX_PIO_WINDOWS;
0195
0196 if (of_property_read_u32(node, "ppio-wins", &pcie->ppio_wins))
0197 pcie->ppio_wins = MAX_PIO_WINDOWS;
0198
0199 return 0;
0200 }
0201
0202 static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie)
0203 {
0204 phys_addr_t msg_addr = pcie->pcie_reg_base;
0205 struct mobiveil_msi *msi = &pcie->rp.msi;
0206
0207 msi->num_of_vectors = PCI_NUM_MSI;
0208 msi->msi_pages_phys = (phys_addr_t)msg_addr;
0209
0210 writel_relaxed(lower_32_bits(msg_addr),
0211 pcie->apb_csr_base + MSI_BASE_LO_OFFSET);
0212 writel_relaxed(upper_32_bits(msg_addr),
0213 pcie->apb_csr_base + MSI_BASE_HI_OFFSET);
0214 writel_relaxed(4096, pcie->apb_csr_base + MSI_SIZE_OFFSET);
0215 writel_relaxed(1, pcie->apb_csr_base + MSI_ENABLE_OFFSET);
0216 }
0217
0218 int mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit)
0219 {
0220 struct mobiveil_root_port *rp = &pcie->rp;
0221 struct pci_host_bridge *bridge = rp->bridge;
0222 u32 value, pab_ctrl, type;
0223 struct resource_entry *win;
0224
0225 pcie->ib_wins_configured = 0;
0226 pcie->ob_wins_configured = 0;
0227
0228 if (!reinit) {
0229
0230 value = mobiveil_csr_readl(pcie, PCI_PRIMARY_BUS);
0231 value &= 0xff000000;
0232 value |= 0x00ff0100;
0233 mobiveil_csr_writel(pcie, value, PCI_PRIMARY_BUS);
0234 }
0235
0236
0237
0238
0239
0240 value = mobiveil_csr_readl(pcie, PCI_COMMAND);
0241 value |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
0242 mobiveil_csr_writel(pcie, value, PCI_COMMAND);
0243
0244
0245
0246
0247
0248 pab_ctrl = mobiveil_csr_readl(pcie, PAB_CTRL);
0249 pab_ctrl |= (1 << AMBA_PIO_ENABLE_SHIFT) | (1 << PEX_PIO_ENABLE_SHIFT);
0250 mobiveil_csr_writel(pcie, pab_ctrl, PAB_CTRL);
0251
0252
0253
0254
0255
0256 value = mobiveil_csr_readl(pcie, PAB_AXI_PIO_CTRL);
0257 value |= APIO_EN_MASK;
0258 mobiveil_csr_writel(pcie, value, PAB_AXI_PIO_CTRL);
0259
0260
0261 value = mobiveil_csr_readl(pcie, PAB_PEX_PIO_CTRL);
0262 value |= 1 << PIO_ENABLE_SHIFT;
0263 mobiveil_csr_writel(pcie, value, PAB_PEX_PIO_CTRL);
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273 program_ob_windows(pcie, WIN_NUM_0, rp->ob_io_res->start, 0,
0274 CFG_WINDOW_TYPE, resource_size(rp->ob_io_res));
0275
0276
0277 program_ib_windows(pcie, WIN_NUM_0, 0, 0, MEM_WINDOW_TYPE, IB_WIN_SIZE);
0278
0279
0280 resource_list_for_each_entry(win, &bridge->windows) {
0281 if (resource_type(win->res) == IORESOURCE_MEM)
0282 type = MEM_WINDOW_TYPE;
0283 else if (resource_type(win->res) == IORESOURCE_IO)
0284 type = IO_WINDOW_TYPE;
0285 else
0286 continue;
0287
0288
0289 program_ob_windows(pcie, pcie->ob_wins_configured,
0290 win->res->start,
0291 win->res->start - win->offset,
0292 type, resource_size(win->res));
0293 }
0294
0295
0296 value = mobiveil_csr_readl(pcie, PAB_INTP_AXI_PIO_CLASS);
0297 value &= 0xff;
0298 value |= PCI_CLASS_BRIDGE_PCI_NORMAL << 8;
0299 mobiveil_csr_writel(pcie, value, PAB_INTP_AXI_PIO_CLASS);
0300
0301 return 0;
0302 }
0303
0304 static void mobiveil_mask_intx_irq(struct irq_data *data)
0305 {
0306 struct mobiveil_pcie *pcie = irq_data_get_irq_chip_data(data);
0307 struct mobiveil_root_port *rp;
0308 unsigned long flags;
0309 u32 mask, shifted_val;
0310
0311 rp = &pcie->rp;
0312 mask = 1 << ((data->hwirq + PAB_INTX_START) - 1);
0313 raw_spin_lock_irqsave(&rp->intx_mask_lock, flags);
0314 shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
0315 shifted_val &= ~mask;
0316 mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
0317 raw_spin_unlock_irqrestore(&rp->intx_mask_lock, flags);
0318 }
0319
0320 static void mobiveil_unmask_intx_irq(struct irq_data *data)
0321 {
0322 struct mobiveil_pcie *pcie = irq_data_get_irq_chip_data(data);
0323 struct mobiveil_root_port *rp;
0324 unsigned long flags;
0325 u32 shifted_val, mask;
0326
0327 rp = &pcie->rp;
0328 mask = 1 << ((data->hwirq + PAB_INTX_START) - 1);
0329 raw_spin_lock_irqsave(&rp->intx_mask_lock, flags);
0330 shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
0331 shifted_val |= mask;
0332 mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
0333 raw_spin_unlock_irqrestore(&rp->intx_mask_lock, flags);
0334 }
0335
0336 static struct irq_chip intx_irq_chip = {
0337 .name = "mobiveil_pcie:intx",
0338 .irq_enable = mobiveil_unmask_intx_irq,
0339 .irq_disable = mobiveil_mask_intx_irq,
0340 .irq_mask = mobiveil_mask_intx_irq,
0341 .irq_unmask = mobiveil_unmask_intx_irq,
0342 };
0343
0344
0345 static int mobiveil_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
0346 irq_hw_number_t hwirq)
0347 {
0348 irq_set_chip_and_handler(irq, &intx_irq_chip, handle_level_irq);
0349 irq_set_chip_data(irq, domain->host_data);
0350
0351 return 0;
0352 }
0353
0354
0355 static const struct irq_domain_ops intx_domain_ops = {
0356 .map = mobiveil_pcie_intx_map,
0357 };
0358
0359 static struct irq_chip mobiveil_msi_irq_chip = {
0360 .name = "Mobiveil PCIe MSI",
0361 .irq_mask = pci_msi_mask_irq,
0362 .irq_unmask = pci_msi_unmask_irq,
0363 };
0364
0365 static struct msi_domain_info mobiveil_msi_domain_info = {
0366 .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
0367 MSI_FLAG_PCI_MSIX),
0368 .chip = &mobiveil_msi_irq_chip,
0369 };
0370
0371 static void mobiveil_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
0372 {
0373 struct mobiveil_pcie *pcie = irq_data_get_irq_chip_data(data);
0374 phys_addr_t addr = pcie->pcie_reg_base + (data->hwirq * sizeof(int));
0375
0376 msg->address_lo = lower_32_bits(addr);
0377 msg->address_hi = upper_32_bits(addr);
0378 msg->data = data->hwirq;
0379
0380 dev_dbg(&pcie->pdev->dev, "msi#%d address_hi %#x address_lo %#x\n",
0381 (int)data->hwirq, msg->address_hi, msg->address_lo);
0382 }
0383
0384 static int mobiveil_msi_set_affinity(struct irq_data *irq_data,
0385 const struct cpumask *mask, bool force)
0386 {
0387 return -EINVAL;
0388 }
0389
0390 static struct irq_chip mobiveil_msi_bottom_irq_chip = {
0391 .name = "Mobiveil MSI",
0392 .irq_compose_msi_msg = mobiveil_compose_msi_msg,
0393 .irq_set_affinity = mobiveil_msi_set_affinity,
0394 };
0395
0396 static int mobiveil_irq_msi_domain_alloc(struct irq_domain *domain,
0397 unsigned int virq,
0398 unsigned int nr_irqs, void *args)
0399 {
0400 struct mobiveil_pcie *pcie = domain->host_data;
0401 struct mobiveil_msi *msi = &pcie->rp.msi;
0402 unsigned long bit;
0403
0404 WARN_ON(nr_irqs != 1);
0405 mutex_lock(&msi->lock);
0406
0407 bit = find_first_zero_bit(msi->msi_irq_in_use, msi->num_of_vectors);
0408 if (bit >= msi->num_of_vectors) {
0409 mutex_unlock(&msi->lock);
0410 return -ENOSPC;
0411 }
0412
0413 set_bit(bit, msi->msi_irq_in_use);
0414
0415 mutex_unlock(&msi->lock);
0416
0417 irq_domain_set_info(domain, virq, bit, &mobiveil_msi_bottom_irq_chip,
0418 domain->host_data, handle_level_irq, NULL, NULL);
0419 return 0;
0420 }
0421
0422 static void mobiveil_irq_msi_domain_free(struct irq_domain *domain,
0423 unsigned int virq,
0424 unsigned int nr_irqs)
0425 {
0426 struct irq_data *d = irq_domain_get_irq_data(domain, virq);
0427 struct mobiveil_pcie *pcie = irq_data_get_irq_chip_data(d);
0428 struct mobiveil_msi *msi = &pcie->rp.msi;
0429
0430 mutex_lock(&msi->lock);
0431
0432 if (!test_bit(d->hwirq, msi->msi_irq_in_use))
0433 dev_err(&pcie->pdev->dev, "trying to free unused MSI#%lu\n",
0434 d->hwirq);
0435 else
0436 __clear_bit(d->hwirq, msi->msi_irq_in_use);
0437
0438 mutex_unlock(&msi->lock);
0439 }
0440 static const struct irq_domain_ops msi_domain_ops = {
0441 .alloc = mobiveil_irq_msi_domain_alloc,
0442 .free = mobiveil_irq_msi_domain_free,
0443 };
0444
0445 static int mobiveil_allocate_msi_domains(struct mobiveil_pcie *pcie)
0446 {
0447 struct device *dev = &pcie->pdev->dev;
0448 struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
0449 struct mobiveil_msi *msi = &pcie->rp.msi;
0450
0451 mutex_init(&msi->lock);
0452 msi->dev_domain = irq_domain_add_linear(NULL, msi->num_of_vectors,
0453 &msi_domain_ops, pcie);
0454 if (!msi->dev_domain) {
0455 dev_err(dev, "failed to create IRQ domain\n");
0456 return -ENOMEM;
0457 }
0458
0459 msi->msi_domain = pci_msi_create_irq_domain(fwnode,
0460 &mobiveil_msi_domain_info,
0461 msi->dev_domain);
0462 if (!msi->msi_domain) {
0463 dev_err(dev, "failed to create MSI domain\n");
0464 irq_domain_remove(msi->dev_domain);
0465 return -ENOMEM;
0466 }
0467
0468 return 0;
0469 }
0470
0471 static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie)
0472 {
0473 struct device *dev = &pcie->pdev->dev;
0474 struct device_node *node = dev->of_node;
0475 struct mobiveil_root_port *rp = &pcie->rp;
0476
0477
0478 rp->intx_domain = irq_domain_add_linear(node, PCI_NUM_INTX,
0479 &intx_domain_ops, pcie);
0480
0481 if (!rp->intx_domain) {
0482 dev_err(dev, "Failed to get a INTx IRQ domain\n");
0483 return -ENOMEM;
0484 }
0485
0486 raw_spin_lock_init(&rp->intx_mask_lock);
0487
0488
0489 return mobiveil_allocate_msi_domains(pcie);
0490 }
0491
0492 static int mobiveil_pcie_integrated_interrupt_init(struct mobiveil_pcie *pcie)
0493 {
0494 struct platform_device *pdev = pcie->pdev;
0495 struct device *dev = &pdev->dev;
0496 struct mobiveil_root_port *rp = &pcie->rp;
0497 struct resource *res;
0498 int ret;
0499
0500
0501 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apb_csr");
0502 pcie->apb_csr_base = devm_pci_remap_cfg_resource(dev, res);
0503 if (IS_ERR(pcie->apb_csr_base))
0504 return PTR_ERR(pcie->apb_csr_base);
0505
0506
0507 mobiveil_pcie_enable_msi(pcie);
0508
0509 rp->irq = platform_get_irq(pdev, 0);
0510 if (rp->irq < 0)
0511 return rp->irq;
0512
0513
0514 ret = mobiveil_pcie_init_irq_domain(pcie);
0515 if (ret) {
0516 dev_err(dev, "Failed creating IRQ Domain\n");
0517 return ret;
0518 }
0519
0520 irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie);
0521
0522
0523 mobiveil_csr_writel(pcie, (PAB_INTP_INTX_MASK | PAB_INTP_MSI_MASK),
0524 PAB_INTP_AMBA_MISC_ENB);
0525
0526
0527 return 0;
0528 }
0529
0530 static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
0531 {
0532 struct mobiveil_root_port *rp = &pcie->rp;
0533
0534 if (rp->ops->interrupt_init)
0535 return rp->ops->interrupt_init(pcie);
0536
0537 return mobiveil_pcie_integrated_interrupt_init(pcie);
0538 }
0539
0540 static bool mobiveil_pcie_is_bridge(struct mobiveil_pcie *pcie)
0541 {
0542 u32 header_type;
0543
0544 header_type = mobiveil_csr_readb(pcie, PCI_HEADER_TYPE);
0545 header_type &= 0x7f;
0546
0547 return header_type == PCI_HEADER_TYPE_BRIDGE;
0548 }
0549
0550 int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
0551 {
0552 struct mobiveil_root_port *rp = &pcie->rp;
0553 struct pci_host_bridge *bridge = rp->bridge;
0554 struct device *dev = &pcie->pdev->dev;
0555 int ret;
0556
0557 ret = mobiveil_pcie_parse_dt(pcie);
0558 if (ret) {
0559 dev_err(dev, "Parsing DT failed, ret: %x\n", ret);
0560 return ret;
0561 }
0562
0563 if (!mobiveil_pcie_is_bridge(pcie))
0564 return -ENODEV;
0565
0566
0567
0568
0569
0570 ret = mobiveil_host_init(pcie, false);
0571 if (ret) {
0572 dev_err(dev, "Failed to initialize host\n");
0573 return ret;
0574 }
0575
0576 ret = mobiveil_pcie_interrupt_init(pcie);
0577 if (ret) {
0578 dev_err(dev, "Interrupt init failed\n");
0579 return ret;
0580 }
0581
0582
0583 bridge->sysdata = pcie;
0584 bridge->ops = &mobiveil_pcie_ops;
0585
0586 ret = mobiveil_bringup_link(pcie);
0587 if (ret) {
0588 dev_info(dev, "link bring-up failed\n");
0589 return ret;
0590 }
0591
0592 return pci_host_probe(bridge);
0593 }