GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / media / pci / mantis / hopper_cards.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3         Hopper 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 <linux/pci.h>
13 #include <linux/slab.h>
14 #include <asm/irq.h>
15 #include <linux/interrupt.h>
16
17 #include <media/dmxdev.h>
18 #include <media/dvbdev.h>
19 #include <media/dvb_demux.h>
20 #include <media/dvb_frontend.h>
21 #include <media/dvb_net.h>
22
23 #include "mantis_common.h"
24 #include "hopper_vp3028.h"
25 #include "mantis_dma.h"
26 #include "mantis_dvb.h"
27 #include "mantis_uart.h"
28 #include "mantis_ioc.h"
29 #include "mantis_pci.h"
30 #include "mantis_i2c.h"
31 #include "mantis_reg.h"
32
33 static unsigned int verbose;
34 module_param(verbose, int, 0644);
35 MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)");
36
37 #define DRIVER_NAME     "Hopper"
38
39 static char *label[10] = {
40         "DMA",
41         "IRQ-0",
42         "IRQ-1",
43         "OCERR",
44         "PABRT",
45         "RIPRR",
46         "PPERR",
47         "FTRGT",
48         "RISCI",
49         "RACK"
50 };
51
52 static int devs;
53
54 static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
55 {
56         u32 stat = 0, mask = 0;
57         u32 rst_stat = 0, rst_mask = 0;
58
59         struct mantis_pci *mantis;
60         struct mantis_ca *ca;
61
62         mantis = (struct mantis_pci *) dev_id;
63         if (unlikely(!mantis))
64                 return IRQ_NONE;
65         ca = mantis->mantis_ca;
66
67         stat = mmread(MANTIS_INT_STAT);
68         mask = mmread(MANTIS_INT_MASK);
69         if (!(stat & mask))
70                 return IRQ_NONE;
71
72         rst_mask  = MANTIS_GPIF_WRACK  |
73                     MANTIS_GPIF_OTHERR |
74                     MANTIS_SBUF_WSTO   |
75                     MANTIS_GPIF_EXTIRQ;
76
77         rst_stat  = mmread(MANTIS_GPIF_STATUS);
78         rst_stat &= rst_mask;
79         mmwrite(rst_stat, MANTIS_GPIF_STATUS);
80
81         mantis->mantis_int_stat = stat;
82         mantis->mantis_int_mask = mask;
83         dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask);
84         if (stat & MANTIS_INT_RISCEN) {
85                 dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]);
86         }
87         if (stat & MANTIS_INT_IRQ0) {
88                 dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]);
89                 mantis->gpif_status = rst_stat;
90                 wake_up(&ca->hif_write_wq);
91                 schedule_work(&ca->hif_evm_work);
92         }
93         if (stat & MANTIS_INT_IRQ1) {
94                 dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
95                 spin_lock(&mantis->intmask_lock);
96                 mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ1,
97                         MANTIS_INT_MASK);
98                 spin_unlock(&mantis->intmask_lock);
99                 schedule_work(&mantis->uart_work);
100         }
101         if (stat & MANTIS_INT_OCERR) {
102                 dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]);
103         }
104         if (stat & MANTIS_INT_PABORT) {
105                 dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]);
106         }
107         if (stat & MANTIS_INT_RIPERR) {
108                 dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]);
109         }
110         if (stat & MANTIS_INT_PPERR) {
111                 dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]);
112         }
113         if (stat & MANTIS_INT_FTRGT) {
114                 dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]);
115         }
116         if (stat & MANTIS_INT_RISCI) {
117                 dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
118                 mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
119                 tasklet_schedule(&mantis->tasklet);
120         }
121         if (stat & MANTIS_INT_I2CDONE) {
122                 dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
123                 wake_up(&mantis->i2c_wq);
124         }
125         mmwrite(stat, MANTIS_INT_STAT);
126         stat &= ~(MANTIS_INT_RISCEN   | MANTIS_INT_I2CDONE |
127                   MANTIS_INT_I2CRACK  | MANTIS_INT_PCMCIA7 |
128                   MANTIS_INT_PCMCIA6  | MANTIS_INT_PCMCIA5 |
129                   MANTIS_INT_PCMCIA4  | MANTIS_INT_PCMCIA3 |
130                   MANTIS_INT_PCMCIA2  | MANTIS_INT_PCMCIA1 |
131                   MANTIS_INT_PCMCIA0  | MANTIS_INT_IRQ1    |
132                   MANTIS_INT_IRQ0     | MANTIS_INT_OCERR   |
133                   MANTIS_INT_PABORT   | MANTIS_INT_RIPERR  |
134                   MANTIS_INT_PPERR    | MANTIS_INT_FTRGT   |
135                   MANTIS_INT_RISCI);
136
137         if (stat)
138                 dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask);
139
140         dprintk(MANTIS_DEBUG, 0, "\n");
141         return IRQ_HANDLED;
142 }
143
144 static int hopper_pci_probe(struct pci_dev *pdev,
145                             const struct pci_device_id *pci_id)
146 {
147         struct mantis_pci_drvdata *drvdata;
148         struct mantis_pci *mantis;
149         struct mantis_hwconfig *config;
150         int err;
151
152         mantis = kzalloc(sizeof(*mantis), GFP_KERNEL);
153         if (!mantis) {
154                 err = -ENOMEM;
155                 goto fail0;
156         }
157
158         drvdata                 = (void *)pci_id->driver_data;
159         mantis->num             = devs;
160         mantis->verbose         = verbose;
161         mantis->pdev            = pdev;
162         config                  = drvdata->hwconfig;
163         config->irq_handler     = &hopper_irq_handler;
164         mantis->hwconfig        = config;
165         mantis->rc_map_name     = drvdata->rc_map_name;
166
167         spin_lock_init(&mantis->intmask_lock);
168
169         err = mantis_pci_init(mantis);
170         if (err) {
171                 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
172                 goto fail1;
173         }
174
175         err = mantis_stream_control(mantis, STREAM_TO_HIF);
176         if (err < 0) {
177                 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
178                 goto fail1;
179         }
180
181         err = mantis_i2c_init(mantis);
182         if (err < 0) {
183                 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
184                 goto fail2;
185         }
186
187         err = mantis_get_mac(mantis);
188         if (err < 0) {
189                 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
190                 goto fail2;
191         }
192
193         err = mantis_dma_init(mantis);
194         if (err < 0) {
195                 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
196                 goto fail3;
197         }
198
199         err = mantis_dvb_init(mantis);
200         if (err < 0) {
201                 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
202                 goto fail4;
203         }
204         devs++;
205
206         return err;
207
208 fail4:
209         dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err);
210         mantis_dma_exit(mantis);
211
212 fail3:
213         dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err);
214         mantis_i2c_exit(mantis);
215
216 fail2:
217         dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err);
218         mantis_pci_exit(mantis);
219
220 fail1:
221         dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err);
222         kfree(mantis);
223
224 fail0:
225         return err;
226 }
227
228 static void hopper_pci_remove(struct pci_dev *pdev)
229 {
230         struct mantis_pci *mantis = pci_get_drvdata(pdev);
231
232         if (mantis) {
233                 mantis_dvb_exit(mantis);
234                 mantis_dma_exit(mantis);
235                 mantis_i2c_exit(mantis);
236                 mantis_pci_exit(mantis);
237                 kfree(mantis);
238         }
239         return;
240
241 }
242
243 static const struct pci_device_id hopper_pci_table[] = {
244         MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config,
245                    NULL),
246         { }
247 };
248
249 MODULE_DEVICE_TABLE(pci, hopper_pci_table);
250
251 static struct pci_driver hopper_pci_driver = {
252         .name           = DRIVER_NAME,
253         .id_table       = hopper_pci_table,
254         .probe          = hopper_pci_probe,
255         .remove         = hopper_pci_remove,
256 };
257
258 module_pci_driver(hopper_pci_driver);
259
260 MODULE_DESCRIPTION("HOPPER driver");
261 MODULE_AUTHOR("Manu Abraham");
262 MODULE_LICENSE("GPL");