#include #include #include #include #include #include #include #include #include #include #include #include #include #include "saa716x_priv.h" #include "saa716x_regs.h" #include "saa716x_budget.h" #define DRIVER_NAME "SAA716x_CORE" unsigned int verbose = 5; module_param(verbose, int, 0644); MODULE_PARM_DESC(verbose, "verbosity level"); static irqreturn_t saa716x_pcie_irq(int irq, void *dev_id) { struct saa716x *saa716x; u32 i2c_stat1, i2c_stat2, mask; if (unlikely((saa716x = (struct saa716x *) dev_id) == NULL)) { printk(KERN_ERR "%s: Aeie NULL ptr\n", __func__); return IRQ_NONE; } // i2c_stat1 = saa716x_read(0xbfe0); // i2c_stat2 = saa716x_read(0xcfe0); dprintk(verbose, SAA716x_DEBUG, 0, "=== Interrupts[Core A: %04x - Core B: %04x] [", i2c_stat1, i2c_stat2); dprintk(verbose, SAA716x_DEBUG, 0, "] ==\n"); return IRQ_HANDLED; } static irqreturn_t saa716x_pcie_irq_msi(int irq, void *dev_id) { struct saa716x *saa716x; if (unlikely((saa716x = (struct saa716x *) dev_id) == NULL)) { printk(KERN_ERR "%s: Aeie NULL ptr\n", __func__); return IRQ_NONE; } return IRQ_HANDLED; } static int saa716x_request_irq(struct saa716x *saa716x) { u32 flags; int err; flags = IRQF_SHARED; #ifdef CONFIG_PCI_MSI saa716x->have_msi = TRUE; if ((err = pci_enable_msi(saa716x->pdev))) { printk("%s ERROR(%d): unable to allocate MSI Interrupt\n", __func__, err); saa716x->have_msi = FALSE; } if (saa716x->have_msi) { flags &= ~IRQF_SHARED; err = request_irq(saa716x->pdev->irq, &saa716x_pcie_irq_msi, flags, DRIVER_NAME, saa716x); if (err) printk("%s ERROR(%d): Unable to allocate Interrupt\n", __func__, err); } else #endif if ((err = request_irq(saa716x->pdev->irq, &saa716x_pcie_irq, flags, DRIVER_NAME, saa716x)) != 0) printk("%s ERROR(%d): Unable to allocate Interrupt\n", __func__, err); return err; } static void saa716x_free_irq(struct saa716x *saa716x) { free_irq(saa716x->pdev->irq, saa716x); #ifdef CONFIG_PCI_MSI if (saa716x->have_msi) pci_disable_msi(saa716x->pdev); #endif } int saa716x_pcie_init(struct saa716x *saa716x) { struct pci_dev *pdev = saa716x->pdev; int err = 0; u8 latency, revision; u32 i2c_stat, int_stat, flags, subsys; unsigned long mmio_start, mmio_len; printk(KERN_INFO "%s: found a %s device\n", __func__, saa716x->hwconfig->model_name); pci_set_drvdata(pdev, saa716x); if ((err = pci_enable_device(pdev)) != 0) { printk(KERN_ERR "%s ERROR: pci enable failed (%i)\n", __func__, err); goto fail0; } if (!(pci_resource_flags(pdev, BAR_0) & IORESOURCE_MEM)) { printk(KERN_ERR "Cannot find proper PCIe device " "base addrress, aborting.\n"); err = -ENODEV; goto fail1; } if ((err = pci_request_region(pdev, BAR_0, DRIVER_NAME)) < 0) { printk(KERN_ERR "%s ERROR: mem region request failed\n", __func__); err = -ENOMEM; goto fail1; } pci_set_master(pdev); mmio_start = pci_resource_start(pdev, BAR_0); mmio_len = pci_resource_len(pdev, BAR_0); err = -EIO; if (!(saa716x->mmio = ioremap(mmio_start, mmio_len))) goto fail2; saa716x->mmio_start = mmio_start; saa716x->mmio_end = mmio_start + mmio_len; err = saa716x_request_irq(saa716x); if (err) goto fail2; pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency); pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); dprintk(verbose, SAA716x_ERROR, 0, " SAA7162 Rev %d [%04x:%04x], ", revision, saa716x->pdev->subsystem_vendor, saa716x->pdev->subsystem_device); dprintk(verbose, SAA716x_ERROR, 0, "irq: %d, latency: %d\n IOMEM: 0x%lx-0x%lx length:0x%lx\n", saa716x->pdev->irq, latency, saa716x->mmio_start, saa716x->mmio_end, mmio_len); dprintk(verbose, SAA716x_ERROR, 0, " MMIO: 0x%p\n", saa716x->mmio); saa716x->verbose = verbose; // init_waitqueue_head(&saa716x->i2c_queue); /* Disable all interrupts here */ // saa716x_write(0, 0x500); // i2c_stat = saa716x_read(0xb008); // int_stat = saa716x_read(0x500); // dprintk(verbose, SAA716x_ERROR, 1, "I2C Status=[0x%04x]", i2c_stat); // dprintk(verbose, SAA716x_ERROR, 1, "INT Status=[0x%04x]", int_stat); subsys = saa716x_read(0x00012000); dprintk(verbose, SAA716x_ERROR, 1, "Subsys:0x%04x", subsys); return 0; fail2: iounmap(saa716x->mmio); release_mem_region(pci_resource_start(saa716x->pdev, 0), pci_resource_len(saa716x->pdev, 0)); fail1: pci_disable_device(pdev); fail0: pci_set_drvdata(pdev, NULL); return err; } EXPORT_SYMBOL_GPL(saa716x_pcie_init); void saa716x_pcie_exit(struct saa716x *saa716x) { struct pci_dev *pdev = saa716x->pdev; u8 command; dprintk(verbose, SAA716x_ERROR, 1, "Unloading .. "); dprintk(verbose, SAA716x_ERROR, 1, "Disabling PCIe Bus Mastering .."); pci_read_config_byte(pdev, PCI_COMMAND, &command); command &= ~PCI_COMMAND_MASTER; pci_write_config_byte(pdev, PCI_COMMAND, command); saa716x_free_irq(saa716x); dprintk(verbose, SAA716x_NOTICE, 1, "SAA716x mem: 0x%p", saa716x->mmio); iounmap(saa716x->mmio); release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } EXPORT_SYMBOL_GPL(saa716x_pcie_exit); MODULE_DESCRIPTION("SAA716x PCIe bridge driver"); MODULE_AUTHOR("Manu Abraham"); MODULE_LICENSE("GPL");