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(dev: 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 = dma_set_coherent_mask(dev: &pdev->dev, 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(dev: 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(dev: pdev, PCI_LATENCY_TIMER, val: &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(irq: pdev->irq, |
102 | handler: config->irq_handler, |
103 | IRQF_SHARED, |
104 | DRIVER_NAME, |
105 | dev: 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, data: 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(addr: 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(dev: 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(addr: mantis->mmio); |
146 | release_mem_region(pci_resource_start(pdev, 0), |
147 | pci_resource_len(pdev, 0)); |
148 | } |
149 | |
150 | pci_disable_device(dev: 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 | |