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 dprintk(MANTIS_ERROR, 1, "Mantis == NULL"); 65 return IRQ_NONE; 66 } 67 ca = mantis->mantis_ca; 68 69 stat = mmread(MANTIS_INT_STAT); 70 mask = mmread(MANTIS_INT_MASK); 71 if (!(stat & mask)) 72 return IRQ_NONE; 73 74 rst_mask = MANTIS_GPIF_WRACK | 75 MANTIS_GPIF_OTHERR | 76 MANTIS_SBUF_WSTO | 77 MANTIS_GPIF_EXTIRQ; 78 79 rst_stat = mmread(MANTIS_GPIF_STATUS); 80 rst_stat &= rst_mask; 81 mmwrite(rst_stat, MANTIS_GPIF_STATUS); 82 83 mantis->mantis_int_stat = stat; 84 mantis->mantis_int_mask = mask; 85 dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask); 86 if (stat & MANTIS_INT_RISCEN) { 87 dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]); 88 } 89 if (stat & MANTIS_INT_IRQ0) { 90 dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]); 91 mantis->gpif_status = rst_stat; 92 wake_up(&ca->hif_write_wq); 93 schedule_work(&ca->hif_evm_work); 94 } 95 if (stat & MANTIS_INT_IRQ1) { 96 dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]); 97 spin_lock(&mantis->intmask_lock); 98 mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ1, 99 MANTIS_INT_MASK); 100 spin_unlock(&mantis->intmask_lock); 101 schedule_work(&mantis->uart_work); 102 } 103 if (stat & MANTIS_INT_OCERR) { 104 dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]); 105 } 106 if (stat & MANTIS_INT_PABORT) { 107 dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]); 108 } 109 if (stat & MANTIS_INT_RIPERR) { 110 dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]); 111 } 112 if (stat & MANTIS_INT_PPERR) { 113 dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]); 114 } 115 if (stat & MANTIS_INT_FTRGT) { 116 dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]); 117 } 118 if (stat & MANTIS_INT_RISCI) { 119 dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]); 120 mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28; 121 tasklet_schedule(&mantis->tasklet); 122 } 123 if (stat & MANTIS_INT_I2CDONE) { 124 dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]); 125 wake_up(&mantis->i2c_wq); 126 } 127 mmwrite(stat, MANTIS_INT_STAT); 128 stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | 129 MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | 130 MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | 131 MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | 132 MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | 133 MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | 134 MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | 135 MANTIS_INT_PABORT | MANTIS_INT_RIPERR | 136 MANTIS_INT_PPERR | MANTIS_INT_FTRGT | 137 MANTIS_INT_RISCI); 138 139 if (stat) 140 dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask); 141 142 dprintk(MANTIS_DEBUG, 0, "\n"); 143 return IRQ_HANDLED; 144 } 145 146 static int hopper_pci_probe(struct pci_dev *pdev, 147 const struct pci_device_id *pci_id) 148 { 149 struct mantis_pci_drvdata *drvdata; 150 struct mantis_pci *mantis; 151 struct mantis_hwconfig *config; 152 int err; 153 154 mantis = kzalloc(sizeof(*mantis), GFP_KERNEL); 155 if (!mantis) { 156 err = -ENOMEM; 157 goto fail0; 158 } 159 160 drvdata = (void *)pci_id->driver_data; 161 mantis->num = devs; 162 mantis->verbose = verbose; 163 mantis->pdev = pdev; 164 config = drvdata->hwconfig; 165 config->irq_handler = &hopper_irq_handler; 166 mantis->hwconfig = config; 167 mantis->rc_map_name = drvdata->rc_map_name; 168 169 spin_lock_init(&mantis->intmask_lock); 170 171 err = mantis_pci_init(mantis); 172 if (err) { 173 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err); 174 goto fail1; 175 } 176 177 err = mantis_stream_control(mantis, STREAM_TO_HIF); 178 if (err < 0) { 179 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err); 180 goto fail1; 181 } 182 183 err = mantis_i2c_init(mantis); 184 if (err < 0) { 185 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err); 186 goto fail2; 187 } 188 189 err = mantis_get_mac(mantis); 190 if (err < 0) { 191 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err); 192 goto fail2; 193 } 194 195 err = mantis_dma_init(mantis); 196 if (err < 0) { 197 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err); 198 goto fail3; 199 } 200 201 err = mantis_dvb_init(mantis); 202 if (err < 0) { 203 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err); 204 goto fail4; 205 } 206 devs++; 207 208 return err; 209 210 fail4: 211 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); 212 mantis_dma_exit(mantis); 213 214 fail3: 215 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err); 216 mantis_i2c_exit(mantis); 217 218 fail2: 219 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err); 220 mantis_pci_exit(mantis); 221 222 fail1: 223 dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err); 224 kfree(mantis); 225 226 fail0: 227 return err; 228 } 229 230 static void hopper_pci_remove(struct pci_dev *pdev) 231 { 232 struct mantis_pci *mantis = pci_get_drvdata(pdev); 233 234 if (mantis) { 235 mantis_dvb_exit(mantis); 236 mantis_dma_exit(mantis); 237 mantis_i2c_exit(mantis); 238 mantis_pci_exit(mantis); 239 kfree(mantis); 240 } 241 return; 242 243 } 244 245 static const struct pci_device_id hopper_pci_table[] = { 246 MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config, 247 NULL), 248 { } 249 }; 250 251 MODULE_DEVICE_TABLE(pci, hopper_pci_table); 252 253 static struct pci_driver hopper_pci_driver = { 254 .name = DRIVER_NAME, 255 .id_table = hopper_pci_table, 256 .probe = hopper_pci_probe, 257 .remove = hopper_pci_remove, 258 }; 259 260 module_pci_driver(hopper_pci_driver); 261 262 MODULE_DESCRIPTION("HOPPER driver"); 263 MODULE_AUTHOR("Manu Abraham"); 264 MODULE_LICENSE("GPL"); 265