1*25aee3deSMauro Carvalho Chehab /* 2*25aee3deSMauro Carvalho Chehab Hopper PCI bridge driver 3*25aee3deSMauro Carvalho Chehab 4*25aee3deSMauro Carvalho Chehab Copyright (C) Manu Abraham (abraham.manu@gmail.com) 5*25aee3deSMauro Carvalho Chehab 6*25aee3deSMauro Carvalho Chehab This program is free software; you can redistribute it and/or modify 7*25aee3deSMauro Carvalho Chehab it under the terms of the GNU General Public License as published by 8*25aee3deSMauro Carvalho Chehab the Free Software Foundation; either version 2 of the License, or 9*25aee3deSMauro Carvalho Chehab (at your option) any later version. 10*25aee3deSMauro Carvalho Chehab 11*25aee3deSMauro Carvalho Chehab This program is distributed in the hope that it will be useful, 12*25aee3deSMauro Carvalho Chehab but WITHOUT ANY WARRANTY; without even the implied warranty of 13*25aee3deSMauro Carvalho Chehab MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*25aee3deSMauro Carvalho Chehab GNU General Public License for more details. 15*25aee3deSMauro Carvalho Chehab 16*25aee3deSMauro Carvalho Chehab You should have received a copy of the GNU General Public License 17*25aee3deSMauro Carvalho Chehab along with this program; if not, write to the Free Software 18*25aee3deSMauro Carvalho Chehab Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*25aee3deSMauro Carvalho Chehab */ 20*25aee3deSMauro Carvalho Chehab 21*25aee3deSMauro Carvalho Chehab #include <linux/module.h> 22*25aee3deSMauro Carvalho Chehab #include <linux/moduleparam.h> 23*25aee3deSMauro Carvalho Chehab #include <linux/kernel.h> 24*25aee3deSMauro Carvalho Chehab #include <linux/pci.h> 25*25aee3deSMauro Carvalho Chehab #include <linux/slab.h> 26*25aee3deSMauro Carvalho Chehab #include <asm/irq.h> 27*25aee3deSMauro Carvalho Chehab #include <linux/interrupt.h> 28*25aee3deSMauro Carvalho Chehab 29*25aee3deSMauro Carvalho Chehab #include "dmxdev.h" 30*25aee3deSMauro Carvalho Chehab #include "dvbdev.h" 31*25aee3deSMauro Carvalho Chehab #include "dvb_demux.h" 32*25aee3deSMauro Carvalho Chehab #include "dvb_frontend.h" 33*25aee3deSMauro Carvalho Chehab #include "dvb_net.h" 34*25aee3deSMauro Carvalho Chehab 35*25aee3deSMauro Carvalho Chehab #include "mantis_common.h" 36*25aee3deSMauro Carvalho Chehab #include "hopper_vp3028.h" 37*25aee3deSMauro Carvalho Chehab #include "mantis_dma.h" 38*25aee3deSMauro Carvalho Chehab #include "mantis_dvb.h" 39*25aee3deSMauro Carvalho Chehab #include "mantis_uart.h" 40*25aee3deSMauro Carvalho Chehab #include "mantis_ioc.h" 41*25aee3deSMauro Carvalho Chehab #include "mantis_pci.h" 42*25aee3deSMauro Carvalho Chehab #include "mantis_i2c.h" 43*25aee3deSMauro Carvalho Chehab #include "mantis_reg.h" 44*25aee3deSMauro Carvalho Chehab 45*25aee3deSMauro Carvalho Chehab static unsigned int verbose; 46*25aee3deSMauro Carvalho Chehab module_param(verbose, int, 0644); 47*25aee3deSMauro Carvalho Chehab MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)"); 48*25aee3deSMauro Carvalho Chehab 49*25aee3deSMauro Carvalho Chehab #define DRIVER_NAME "Hopper" 50*25aee3deSMauro Carvalho Chehab 51*25aee3deSMauro Carvalho Chehab static char *label[10] = { 52*25aee3deSMauro Carvalho Chehab "DMA", 53*25aee3deSMauro Carvalho Chehab "IRQ-0", 54*25aee3deSMauro Carvalho Chehab "IRQ-1", 55*25aee3deSMauro Carvalho Chehab "OCERR", 56*25aee3deSMauro Carvalho Chehab "PABRT", 57*25aee3deSMauro Carvalho Chehab "RIPRR", 58*25aee3deSMauro Carvalho Chehab "PPERR", 59*25aee3deSMauro Carvalho Chehab "FTRGT", 60*25aee3deSMauro Carvalho Chehab "RISCI", 61*25aee3deSMauro Carvalho Chehab "RACK" 62*25aee3deSMauro Carvalho Chehab }; 63*25aee3deSMauro Carvalho Chehab 64*25aee3deSMauro Carvalho Chehab static int devs; 65*25aee3deSMauro Carvalho Chehab 66*25aee3deSMauro Carvalho Chehab static irqreturn_t hopper_irq_handler(int irq, void *dev_id) 67*25aee3deSMauro Carvalho Chehab { 68*25aee3deSMauro Carvalho Chehab u32 stat = 0, mask = 0; 69*25aee3deSMauro Carvalho Chehab u32 rst_stat = 0, rst_mask = 0; 70*25aee3deSMauro Carvalho Chehab 71*25aee3deSMauro Carvalho Chehab struct mantis_pci *mantis; 72*25aee3deSMauro Carvalho Chehab struct mantis_ca *ca; 73*25aee3deSMauro Carvalho Chehab 74*25aee3deSMauro Carvalho Chehab mantis = (struct mantis_pci *) dev_id; 75*25aee3deSMauro Carvalho Chehab if (unlikely(mantis == NULL)) { 76*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_ERROR, 1, "Mantis == NULL"); 77*25aee3deSMauro Carvalho Chehab return IRQ_NONE; 78*25aee3deSMauro Carvalho Chehab } 79*25aee3deSMauro Carvalho Chehab ca = mantis->mantis_ca; 80*25aee3deSMauro Carvalho Chehab 81*25aee3deSMauro Carvalho Chehab stat = mmread(MANTIS_INT_STAT); 82*25aee3deSMauro Carvalho Chehab mask = mmread(MANTIS_INT_MASK); 83*25aee3deSMauro Carvalho Chehab if (!(stat & mask)) 84*25aee3deSMauro Carvalho Chehab return IRQ_NONE; 85*25aee3deSMauro Carvalho Chehab 86*25aee3deSMauro Carvalho Chehab rst_mask = MANTIS_GPIF_WRACK | 87*25aee3deSMauro Carvalho Chehab MANTIS_GPIF_OTHERR | 88*25aee3deSMauro Carvalho Chehab MANTIS_SBUF_WSTO | 89*25aee3deSMauro Carvalho Chehab MANTIS_GPIF_EXTIRQ; 90*25aee3deSMauro Carvalho Chehab 91*25aee3deSMauro Carvalho Chehab rst_stat = mmread(MANTIS_GPIF_STATUS); 92*25aee3deSMauro Carvalho Chehab rst_stat &= rst_mask; 93*25aee3deSMauro Carvalho Chehab mmwrite(rst_stat, MANTIS_GPIF_STATUS); 94*25aee3deSMauro Carvalho Chehab 95*25aee3deSMauro Carvalho Chehab mantis->mantis_int_stat = stat; 96*25aee3deSMauro Carvalho Chehab mantis->mantis_int_mask = mask; 97*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask); 98*25aee3deSMauro Carvalho Chehab if (stat & MANTIS_INT_RISCEN) { 99*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]); 100*25aee3deSMauro Carvalho Chehab } 101*25aee3deSMauro Carvalho Chehab if (stat & MANTIS_INT_IRQ0) { 102*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]); 103*25aee3deSMauro Carvalho Chehab mantis->gpif_status = rst_stat; 104*25aee3deSMauro Carvalho Chehab wake_up(&ca->hif_write_wq); 105*25aee3deSMauro Carvalho Chehab schedule_work(&ca->hif_evm_work); 106*25aee3deSMauro Carvalho Chehab } 107*25aee3deSMauro Carvalho Chehab if (stat & MANTIS_INT_IRQ1) { 108*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]); 109*25aee3deSMauro Carvalho Chehab schedule_work(&mantis->uart_work); 110*25aee3deSMauro Carvalho Chehab } 111*25aee3deSMauro Carvalho Chehab if (stat & MANTIS_INT_OCERR) { 112*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]); 113*25aee3deSMauro Carvalho Chehab } 114*25aee3deSMauro Carvalho Chehab if (stat & MANTIS_INT_PABORT) { 115*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]); 116*25aee3deSMauro Carvalho Chehab } 117*25aee3deSMauro Carvalho Chehab if (stat & MANTIS_INT_RIPERR) { 118*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]); 119*25aee3deSMauro Carvalho Chehab } 120*25aee3deSMauro Carvalho Chehab if (stat & MANTIS_INT_PPERR) { 121*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]); 122*25aee3deSMauro Carvalho Chehab } 123*25aee3deSMauro Carvalho Chehab if (stat & MANTIS_INT_FTRGT) { 124*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]); 125*25aee3deSMauro Carvalho Chehab } 126*25aee3deSMauro Carvalho Chehab if (stat & MANTIS_INT_RISCI) { 127*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]); 128*25aee3deSMauro Carvalho Chehab mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28; 129*25aee3deSMauro Carvalho Chehab tasklet_schedule(&mantis->tasklet); 130*25aee3deSMauro Carvalho Chehab } 131*25aee3deSMauro Carvalho Chehab if (stat & MANTIS_INT_I2CDONE) { 132*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]); 133*25aee3deSMauro Carvalho Chehab wake_up(&mantis->i2c_wq); 134*25aee3deSMauro Carvalho Chehab } 135*25aee3deSMauro Carvalho Chehab mmwrite(stat, MANTIS_INT_STAT); 136*25aee3deSMauro Carvalho Chehab stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | 137*25aee3deSMauro Carvalho Chehab MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | 138*25aee3deSMauro Carvalho Chehab MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | 139*25aee3deSMauro Carvalho Chehab MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | 140*25aee3deSMauro Carvalho Chehab MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | 141*25aee3deSMauro Carvalho Chehab MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | 142*25aee3deSMauro Carvalho Chehab MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | 143*25aee3deSMauro Carvalho Chehab MANTIS_INT_PABORT | MANTIS_INT_RIPERR | 144*25aee3deSMauro Carvalho Chehab MANTIS_INT_PPERR | MANTIS_INT_FTRGT | 145*25aee3deSMauro Carvalho Chehab MANTIS_INT_RISCI); 146*25aee3deSMauro Carvalho Chehab 147*25aee3deSMauro Carvalho Chehab if (stat) 148*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask); 149*25aee3deSMauro Carvalho Chehab 150*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_DEBUG, 0, "\n"); 151*25aee3deSMauro Carvalho Chehab return IRQ_HANDLED; 152*25aee3deSMauro Carvalho Chehab } 153*25aee3deSMauro Carvalho Chehab 154*25aee3deSMauro Carvalho Chehab static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) 155*25aee3deSMauro Carvalho Chehab { 156*25aee3deSMauro Carvalho Chehab struct mantis_pci *mantis; 157*25aee3deSMauro Carvalho Chehab struct mantis_hwconfig *config; 158*25aee3deSMauro Carvalho Chehab int err = 0; 159*25aee3deSMauro Carvalho Chehab 160*25aee3deSMauro Carvalho Chehab mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL); 161*25aee3deSMauro Carvalho Chehab if (mantis == NULL) { 162*25aee3deSMauro Carvalho Chehab printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); 163*25aee3deSMauro Carvalho Chehab err = -ENOMEM; 164*25aee3deSMauro Carvalho Chehab goto fail0; 165*25aee3deSMauro Carvalho Chehab } 166*25aee3deSMauro Carvalho Chehab 167*25aee3deSMauro Carvalho Chehab mantis->num = devs; 168*25aee3deSMauro Carvalho Chehab mantis->verbose = verbose; 169*25aee3deSMauro Carvalho Chehab mantis->pdev = pdev; 170*25aee3deSMauro Carvalho Chehab config = (struct mantis_hwconfig *) pci_id->driver_data; 171*25aee3deSMauro Carvalho Chehab config->irq_handler = &hopper_irq_handler; 172*25aee3deSMauro Carvalho Chehab mantis->hwconfig = config; 173*25aee3deSMauro Carvalho Chehab 174*25aee3deSMauro Carvalho Chehab err = mantis_pci_init(mantis); 175*25aee3deSMauro Carvalho Chehab if (err) { 176*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err); 177*25aee3deSMauro Carvalho Chehab goto fail1; 178*25aee3deSMauro Carvalho Chehab } 179*25aee3deSMauro Carvalho Chehab 180*25aee3deSMauro Carvalho Chehab err = mantis_stream_control(mantis, STREAM_TO_HIF); 181*25aee3deSMauro Carvalho Chehab if (err < 0) { 182*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err); 183*25aee3deSMauro Carvalho Chehab goto fail1; 184*25aee3deSMauro Carvalho Chehab } 185*25aee3deSMauro Carvalho Chehab 186*25aee3deSMauro Carvalho Chehab err = mantis_i2c_init(mantis); 187*25aee3deSMauro Carvalho Chehab if (err < 0) { 188*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err); 189*25aee3deSMauro Carvalho Chehab goto fail2; 190*25aee3deSMauro Carvalho Chehab } 191*25aee3deSMauro Carvalho Chehab 192*25aee3deSMauro Carvalho Chehab err = mantis_get_mac(mantis); 193*25aee3deSMauro Carvalho Chehab if (err < 0) { 194*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err); 195*25aee3deSMauro Carvalho Chehab goto fail2; 196*25aee3deSMauro Carvalho Chehab } 197*25aee3deSMauro Carvalho Chehab 198*25aee3deSMauro Carvalho Chehab err = mantis_dma_init(mantis); 199*25aee3deSMauro Carvalho Chehab if (err < 0) { 200*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err); 201*25aee3deSMauro Carvalho Chehab goto fail3; 202*25aee3deSMauro Carvalho Chehab } 203*25aee3deSMauro Carvalho Chehab 204*25aee3deSMauro Carvalho Chehab err = mantis_dvb_init(mantis); 205*25aee3deSMauro Carvalho Chehab if (err < 0) { 206*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err); 207*25aee3deSMauro Carvalho Chehab goto fail4; 208*25aee3deSMauro Carvalho Chehab } 209*25aee3deSMauro Carvalho Chehab devs++; 210*25aee3deSMauro Carvalho Chehab 211*25aee3deSMauro Carvalho Chehab return err; 212*25aee3deSMauro Carvalho Chehab 213*25aee3deSMauro Carvalho Chehab fail4: 214*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); 215*25aee3deSMauro Carvalho Chehab mantis_dma_exit(mantis); 216*25aee3deSMauro Carvalho Chehab 217*25aee3deSMauro Carvalho Chehab fail3: 218*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err); 219*25aee3deSMauro Carvalho Chehab mantis_i2c_exit(mantis); 220*25aee3deSMauro Carvalho Chehab 221*25aee3deSMauro Carvalho Chehab fail2: 222*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err); 223*25aee3deSMauro Carvalho Chehab mantis_pci_exit(mantis); 224*25aee3deSMauro Carvalho Chehab 225*25aee3deSMauro Carvalho Chehab fail1: 226*25aee3deSMauro Carvalho Chehab dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err); 227*25aee3deSMauro Carvalho Chehab kfree(mantis); 228*25aee3deSMauro Carvalho Chehab 229*25aee3deSMauro Carvalho Chehab fail0: 230*25aee3deSMauro Carvalho Chehab return err; 231*25aee3deSMauro Carvalho Chehab } 232*25aee3deSMauro Carvalho Chehab 233*25aee3deSMauro Carvalho Chehab static void __devexit hopper_pci_remove(struct pci_dev *pdev) 234*25aee3deSMauro Carvalho Chehab { 235*25aee3deSMauro Carvalho Chehab struct mantis_pci *mantis = pci_get_drvdata(pdev); 236*25aee3deSMauro Carvalho Chehab 237*25aee3deSMauro Carvalho Chehab if (mantis) { 238*25aee3deSMauro Carvalho Chehab mantis_dvb_exit(mantis); 239*25aee3deSMauro Carvalho Chehab mantis_dma_exit(mantis); 240*25aee3deSMauro Carvalho Chehab mantis_i2c_exit(mantis); 241*25aee3deSMauro Carvalho Chehab mantis_pci_exit(mantis); 242*25aee3deSMauro Carvalho Chehab kfree(mantis); 243*25aee3deSMauro Carvalho Chehab } 244*25aee3deSMauro Carvalho Chehab return; 245*25aee3deSMauro Carvalho Chehab 246*25aee3deSMauro Carvalho Chehab } 247*25aee3deSMauro Carvalho Chehab 248*25aee3deSMauro Carvalho Chehab static struct pci_device_id hopper_pci_table[] = { 249*25aee3deSMauro Carvalho Chehab MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config), 250*25aee3deSMauro Carvalho Chehab { } 251*25aee3deSMauro Carvalho Chehab }; 252*25aee3deSMauro Carvalho Chehab 253*25aee3deSMauro Carvalho Chehab MODULE_DEVICE_TABLE(pci, hopper_pci_table); 254*25aee3deSMauro Carvalho Chehab 255*25aee3deSMauro Carvalho Chehab static struct pci_driver hopper_pci_driver = { 256*25aee3deSMauro Carvalho Chehab .name = DRIVER_NAME, 257*25aee3deSMauro Carvalho Chehab .id_table = hopper_pci_table, 258*25aee3deSMauro Carvalho Chehab .probe = hopper_pci_probe, 259*25aee3deSMauro Carvalho Chehab .remove = hopper_pci_remove, 260*25aee3deSMauro Carvalho Chehab }; 261*25aee3deSMauro Carvalho Chehab 262*25aee3deSMauro Carvalho Chehab static int __devinit hopper_init(void) 263*25aee3deSMauro Carvalho Chehab { 264*25aee3deSMauro Carvalho Chehab return pci_register_driver(&hopper_pci_driver); 265*25aee3deSMauro Carvalho Chehab } 266*25aee3deSMauro Carvalho Chehab 267*25aee3deSMauro Carvalho Chehab static void __devexit hopper_exit(void) 268*25aee3deSMauro Carvalho Chehab { 269*25aee3deSMauro Carvalho Chehab return pci_unregister_driver(&hopper_pci_driver); 270*25aee3deSMauro Carvalho Chehab } 271*25aee3deSMauro Carvalho Chehab 272*25aee3deSMauro Carvalho Chehab module_init(hopper_init); 273*25aee3deSMauro Carvalho Chehab module_exit(hopper_exit); 274*25aee3deSMauro Carvalho Chehab 275*25aee3deSMauro Carvalho Chehab MODULE_DESCRIPTION("HOPPER driver"); 276*25aee3deSMauro Carvalho Chehab MODULE_AUTHOR("Manu Abraham"); 277*25aee3deSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 278