1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 Mantis PCI bridge driver 4 5 Copyright (C) Manu Abraham (abraham.manu@gmail.com) 6 7 */ 8 9 #include <linux/module.h> 10 #include <linux/moduleparam.h> 11 #include <linux/kernel.h> 12 #include <asm/io.h> 13 #include <asm/page.h> 14 #include <linux/kmod.h> 15 #include <linux/vmalloc.h> 16 #include <linux/init.h> 17 #include <linux/device.h> 18 #include <linux/pci.h> 19 20 #include <asm/irq.h> 21 #include <linux/signal.h> 22 #include <linux/sched.h> 23 #include <linux/interrupt.h> 24 25 #include <media/dmxdev.h> 26 #include <media/dvbdev.h> 27 #include <media/dvb_demux.h> 28 #include <media/dvb_frontend.h> 29 #include <media/dvb_net.h> 30 31 #include "mantis_common.h" 32 #include "mantis_reg.h" 33 #include "mantis_pci.h" 34 35 #define DRIVER_NAME "Mantis Core" 36 37 int mantis_pci_init(struct mantis_pci *mantis) 38 { 39 u8 latency; 40 struct mantis_hwconfig *config = mantis->hwconfig; 41 struct pci_dev *pdev = mantis->pdev; 42 int err, ret = 0; 43 44 dprintk(MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n", 45 config->model_name, 46 config->dev_type, 47 mantis->pdev->bus->number, 48 PCI_SLOT(mantis->pdev->devfn), 49 PCI_FUNC(mantis->pdev->devfn)); 50 51 err = pci_enable_device(pdev); 52 if (err != 0) { 53 ret = -ENODEV; 54 dprintk(MANTIS_ERROR, 1, "ERROR: PCI enable failed <%i>", err); 55 goto fail0; 56 } 57 58 err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 59 if (err != 0) { 60 dprintk(MANTIS_ERROR, 1, "ERROR: Unable to obtain 32 bit DMA <%i>", err); 61 ret = -ENOMEM; 62 goto fail1; 63 } 64 65 pci_set_master(pdev); 66 67 if (!request_mem_region(pci_resource_start(pdev, 0), 68 pci_resource_len(pdev, 0), 69 DRIVER_NAME)) { 70 71 dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 Request failed !"); 72 ret = -ENODEV; 73 goto fail1; 74 } 75 76 mantis->mmio = ioremap(pci_resource_start(pdev, 0), 77 pci_resource_len(pdev, 0)); 78 79 if (!mantis->mmio) { 80 dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 remap failed !"); 81 ret = -ENODEV; 82 goto fail2; 83 } 84 85 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency); 86 mantis->latency = latency; 87 mantis->revision = pdev->revision; 88 89 dprintk(MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ", 90 mantis->revision, 91 mantis->pdev->subsystem_vendor, 92 mantis->pdev->subsystem_device); 93 94 dprintk(MANTIS_ERROR, 0, 95 "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", 96 mantis->pdev->irq, 97 mantis->latency, 98 mantis->mantis_addr, 99 mantis->mmio); 100 101 err = request_irq(pdev->irq, 102 config->irq_handler, 103 IRQF_SHARED, 104 DRIVER_NAME, 105 mantis); 106 107 if (err != 0) { 108 109 dprintk(MANTIS_ERROR, 1, "ERROR: IRQ registration failed ! <%d>", err); 110 ret = -ENODEV; 111 goto fail3; 112 } 113 114 pci_set_drvdata(pdev, mantis); 115 return ret; 116 117 /* Error conditions */ 118 fail3: 119 dprintk(MANTIS_ERROR, 1, "ERROR: <%d> I/O unmap", ret); 120 if (mantis->mmio) 121 iounmap(mantis->mmio); 122 123 fail2: 124 dprintk(MANTIS_ERROR, 1, "ERROR: <%d> releasing regions", ret); 125 release_mem_region(pci_resource_start(pdev, 0), 126 pci_resource_len(pdev, 0)); 127 128 fail1: 129 dprintk(MANTIS_ERROR, 1, "ERROR: <%d> disabling device", ret); 130 pci_disable_device(pdev); 131 132 fail0: 133 dprintk(MANTIS_ERROR, 1, "ERROR: <%d> exiting", ret); 134 return ret; 135 } 136 EXPORT_SYMBOL_GPL(mantis_pci_init); 137 138 void mantis_pci_exit(struct mantis_pci *mantis) 139 { 140 struct pci_dev *pdev = mantis->pdev; 141 142 dprintk(MANTIS_NOTICE, 1, " mem: 0x%p", mantis->mmio); 143 free_irq(pdev->irq, mantis); 144 if (mantis->mmio) { 145 iounmap(mantis->mmio); 146 release_mem_region(pci_resource_start(pdev, 0), 147 pci_resource_len(pdev, 0)); 148 } 149 150 pci_disable_device(pdev); 151 } 152 EXPORT_SYMBOL_GPL(mantis_pci_exit); 153 154 MODULE_DESCRIPTION("Mantis PCI DTV bridge driver"); 155 MODULE_AUTHOR("Manu Abraham"); 156 MODULE_LICENSE("GPL"); 157