xref: /openbmc/linux/drivers/media/pci/mantis/hopper_cards.c (revision d303b7c5b2660d93ba0dd2bf99b7dfa7bb93de73)
125aee3deSMauro Carvalho Chehab /*
225aee3deSMauro Carvalho Chehab 	Hopper PCI bridge driver
325aee3deSMauro Carvalho Chehab 
425aee3deSMauro Carvalho Chehab 	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
525aee3deSMauro Carvalho Chehab 
625aee3deSMauro Carvalho Chehab 	This program is free software; you can redistribute it and/or modify
725aee3deSMauro Carvalho Chehab 	it under the terms of the GNU General Public License as published by
825aee3deSMauro Carvalho Chehab 	the Free Software Foundation; either version 2 of the License, or
925aee3deSMauro Carvalho Chehab 	(at your option) any later version.
1025aee3deSMauro Carvalho Chehab 
1125aee3deSMauro Carvalho Chehab 	This program is distributed in the hope that it will be useful,
1225aee3deSMauro Carvalho Chehab 	but WITHOUT ANY WARRANTY; without even the implied warranty of
1325aee3deSMauro Carvalho Chehab 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1425aee3deSMauro Carvalho Chehab 	GNU General Public License for more details.
1525aee3deSMauro Carvalho Chehab 
1625aee3deSMauro Carvalho Chehab 	You should have received a copy of the GNU General Public License
1725aee3deSMauro Carvalho Chehab 	along with this program; if not, write to the Free Software
1825aee3deSMauro Carvalho Chehab 	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1925aee3deSMauro Carvalho Chehab */
2025aee3deSMauro Carvalho Chehab 
2125aee3deSMauro Carvalho Chehab #include <linux/module.h>
2225aee3deSMauro Carvalho Chehab #include <linux/moduleparam.h>
2325aee3deSMauro Carvalho Chehab #include <linux/kernel.h>
2425aee3deSMauro Carvalho Chehab #include <linux/pci.h>
2525aee3deSMauro Carvalho Chehab #include <linux/slab.h>
2625aee3deSMauro Carvalho Chehab #include <asm/irq.h>
2725aee3deSMauro Carvalho Chehab #include <linux/interrupt.h>
2825aee3deSMauro Carvalho Chehab 
2925aee3deSMauro Carvalho Chehab #include "dmxdev.h"
3025aee3deSMauro Carvalho Chehab #include "dvbdev.h"
3125aee3deSMauro Carvalho Chehab #include "dvb_demux.h"
3225aee3deSMauro Carvalho Chehab #include "dvb_frontend.h"
3325aee3deSMauro Carvalho Chehab #include "dvb_net.h"
3425aee3deSMauro Carvalho Chehab 
3525aee3deSMauro Carvalho Chehab #include "mantis_common.h"
3625aee3deSMauro Carvalho Chehab #include "hopper_vp3028.h"
3725aee3deSMauro Carvalho Chehab #include "mantis_dma.h"
3825aee3deSMauro Carvalho Chehab #include "mantis_dvb.h"
3925aee3deSMauro Carvalho Chehab #include "mantis_uart.h"
4025aee3deSMauro Carvalho Chehab #include "mantis_ioc.h"
4125aee3deSMauro Carvalho Chehab #include "mantis_pci.h"
4225aee3deSMauro Carvalho Chehab #include "mantis_i2c.h"
4325aee3deSMauro Carvalho Chehab #include "mantis_reg.h"
4425aee3deSMauro Carvalho Chehab 
4525aee3deSMauro Carvalho Chehab static unsigned int verbose;
4625aee3deSMauro Carvalho Chehab module_param(verbose, int, 0644);
4725aee3deSMauro Carvalho Chehab MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)");
4825aee3deSMauro Carvalho Chehab 
4925aee3deSMauro Carvalho Chehab #define DRIVER_NAME	"Hopper"
5025aee3deSMauro Carvalho Chehab 
5125aee3deSMauro Carvalho Chehab static char *label[10] = {
5225aee3deSMauro Carvalho Chehab 	"DMA",
5325aee3deSMauro Carvalho Chehab 	"IRQ-0",
5425aee3deSMauro Carvalho Chehab 	"IRQ-1",
5525aee3deSMauro Carvalho Chehab 	"OCERR",
5625aee3deSMauro Carvalho Chehab 	"PABRT",
5725aee3deSMauro Carvalho Chehab 	"RIPRR",
5825aee3deSMauro Carvalho Chehab 	"PPERR",
5925aee3deSMauro Carvalho Chehab 	"FTRGT",
6025aee3deSMauro Carvalho Chehab 	"RISCI",
6125aee3deSMauro Carvalho Chehab 	"RACK"
6225aee3deSMauro Carvalho Chehab };
6325aee3deSMauro Carvalho Chehab 
6425aee3deSMauro Carvalho Chehab static int devs;
6525aee3deSMauro Carvalho Chehab 
6625aee3deSMauro Carvalho Chehab static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
6725aee3deSMauro Carvalho Chehab {
6825aee3deSMauro Carvalho Chehab 	u32 stat = 0, mask = 0;
6925aee3deSMauro Carvalho Chehab 	u32 rst_stat = 0, rst_mask = 0;
7025aee3deSMauro Carvalho Chehab 
7125aee3deSMauro Carvalho Chehab 	struct mantis_pci *mantis;
7225aee3deSMauro Carvalho Chehab 	struct mantis_ca *ca;
7325aee3deSMauro Carvalho Chehab 
7425aee3deSMauro Carvalho Chehab 	mantis = (struct mantis_pci *) dev_id;
7525aee3deSMauro Carvalho Chehab 	if (unlikely(mantis == NULL)) {
7625aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_ERROR, 1, "Mantis == NULL");
7725aee3deSMauro Carvalho Chehab 		return IRQ_NONE;
7825aee3deSMauro Carvalho Chehab 	}
7925aee3deSMauro Carvalho Chehab 	ca = mantis->mantis_ca;
8025aee3deSMauro Carvalho Chehab 
8125aee3deSMauro Carvalho Chehab 	stat = mmread(MANTIS_INT_STAT);
8225aee3deSMauro Carvalho Chehab 	mask = mmread(MANTIS_INT_MASK);
8325aee3deSMauro Carvalho Chehab 	if (!(stat & mask))
8425aee3deSMauro Carvalho Chehab 		return IRQ_NONE;
8525aee3deSMauro Carvalho Chehab 
8625aee3deSMauro Carvalho Chehab 	rst_mask  = MANTIS_GPIF_WRACK  |
8725aee3deSMauro Carvalho Chehab 		    MANTIS_GPIF_OTHERR |
8825aee3deSMauro Carvalho Chehab 		    MANTIS_SBUF_WSTO   |
8925aee3deSMauro Carvalho Chehab 		    MANTIS_GPIF_EXTIRQ;
9025aee3deSMauro Carvalho Chehab 
9125aee3deSMauro Carvalho Chehab 	rst_stat  = mmread(MANTIS_GPIF_STATUS);
9225aee3deSMauro Carvalho Chehab 	rst_stat &= rst_mask;
9325aee3deSMauro Carvalho Chehab 	mmwrite(rst_stat, MANTIS_GPIF_STATUS);
9425aee3deSMauro Carvalho Chehab 
9525aee3deSMauro Carvalho Chehab 	mantis->mantis_int_stat = stat;
9625aee3deSMauro Carvalho Chehab 	mantis->mantis_int_mask = mask;
9725aee3deSMauro Carvalho Chehab 	dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask);
9825aee3deSMauro Carvalho Chehab 	if (stat & MANTIS_INT_RISCEN) {
9925aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]);
10025aee3deSMauro Carvalho Chehab 	}
10125aee3deSMauro Carvalho Chehab 	if (stat & MANTIS_INT_IRQ0) {
10225aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]);
10325aee3deSMauro Carvalho Chehab 		mantis->gpif_status = rst_stat;
10425aee3deSMauro Carvalho Chehab 		wake_up(&ca->hif_write_wq);
10525aee3deSMauro Carvalho Chehab 		schedule_work(&ca->hif_evm_work);
10625aee3deSMauro Carvalho Chehab 	}
10725aee3deSMauro Carvalho Chehab 	if (stat & MANTIS_INT_IRQ1) {
10825aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
109a96762daSJan Klötzke 		spin_lock(&mantis->intmask_lock);
1109d605e63SMauro Carvalho Chehab 		mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ1,
1119d605e63SMauro Carvalho Chehab 			MANTIS_INT_MASK);
112a96762daSJan Klötzke 		spin_unlock(&mantis->intmask_lock);
11325aee3deSMauro Carvalho Chehab 		schedule_work(&mantis->uart_work);
11425aee3deSMauro Carvalho Chehab 	}
11525aee3deSMauro Carvalho Chehab 	if (stat & MANTIS_INT_OCERR) {
11625aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]);
11725aee3deSMauro Carvalho Chehab 	}
11825aee3deSMauro Carvalho Chehab 	if (stat & MANTIS_INT_PABORT) {
11925aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]);
12025aee3deSMauro Carvalho Chehab 	}
12125aee3deSMauro Carvalho Chehab 	if (stat & MANTIS_INT_RIPERR) {
12225aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]);
12325aee3deSMauro Carvalho Chehab 	}
12425aee3deSMauro Carvalho Chehab 	if (stat & MANTIS_INT_PPERR) {
12525aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]);
12625aee3deSMauro Carvalho Chehab 	}
12725aee3deSMauro Carvalho Chehab 	if (stat & MANTIS_INT_FTRGT) {
12825aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]);
12925aee3deSMauro Carvalho Chehab 	}
13025aee3deSMauro Carvalho Chehab 	if (stat & MANTIS_INT_RISCI) {
13125aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
13225aee3deSMauro Carvalho Chehab 		mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
13325aee3deSMauro Carvalho Chehab 		tasklet_schedule(&mantis->tasklet);
13425aee3deSMauro Carvalho Chehab 	}
13525aee3deSMauro Carvalho Chehab 	if (stat & MANTIS_INT_I2CDONE) {
13625aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
13725aee3deSMauro Carvalho Chehab 		wake_up(&mantis->i2c_wq);
13825aee3deSMauro Carvalho Chehab 	}
13925aee3deSMauro Carvalho Chehab 	mmwrite(stat, MANTIS_INT_STAT);
14025aee3deSMauro Carvalho Chehab 	stat &= ~(MANTIS_INT_RISCEN   | MANTIS_INT_I2CDONE |
14125aee3deSMauro Carvalho Chehab 		  MANTIS_INT_I2CRACK  | MANTIS_INT_PCMCIA7 |
14225aee3deSMauro Carvalho Chehab 		  MANTIS_INT_PCMCIA6  | MANTIS_INT_PCMCIA5 |
14325aee3deSMauro Carvalho Chehab 		  MANTIS_INT_PCMCIA4  | MANTIS_INT_PCMCIA3 |
14425aee3deSMauro Carvalho Chehab 		  MANTIS_INT_PCMCIA2  | MANTIS_INT_PCMCIA1 |
14525aee3deSMauro Carvalho Chehab 		  MANTIS_INT_PCMCIA0  | MANTIS_INT_IRQ1	   |
14625aee3deSMauro Carvalho Chehab 		  MANTIS_INT_IRQ0     | MANTIS_INT_OCERR   |
14725aee3deSMauro Carvalho Chehab 		  MANTIS_INT_PABORT   | MANTIS_INT_RIPERR  |
14825aee3deSMauro Carvalho Chehab 		  MANTIS_INT_PPERR    | MANTIS_INT_FTRGT   |
14925aee3deSMauro Carvalho Chehab 		  MANTIS_INT_RISCI);
15025aee3deSMauro Carvalho Chehab 
15125aee3deSMauro Carvalho Chehab 	if (stat)
15225aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask);
15325aee3deSMauro Carvalho Chehab 
15425aee3deSMauro Carvalho Chehab 	dprintk(MANTIS_DEBUG, 0, "\n");
15525aee3deSMauro Carvalho Chehab 	return IRQ_HANDLED;
15625aee3deSMauro Carvalho Chehab }
15725aee3deSMauro Carvalho Chehab 
1584c62e976SGreg Kroah-Hartman static int hopper_pci_probe(struct pci_dev *pdev,
1594c62e976SGreg Kroah-Hartman 			    const struct pci_device_id *pci_id)
16025aee3deSMauro Carvalho Chehab {
161a96762daSJan Klötzke 	struct mantis_pci_drvdata *drvdata;
16225aee3deSMauro Carvalho Chehab 	struct mantis_pci *mantis;
16325aee3deSMauro Carvalho Chehab 	struct mantis_hwconfig *config;
164*d303b7c5SMarkus Elfring 	int err;
16525aee3deSMauro Carvalho Chehab 
16625aee3deSMauro Carvalho Chehab 	mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL);
16725aee3deSMauro Carvalho Chehab 	if (mantis == NULL) {
16825aee3deSMauro Carvalho Chehab 		err = -ENOMEM;
16925aee3deSMauro Carvalho Chehab 		goto fail0;
17025aee3deSMauro Carvalho Chehab 	}
17125aee3deSMauro Carvalho Chehab 
1729d605e63SMauro Carvalho Chehab 	drvdata			= (void *)pci_id->driver_data;
17325aee3deSMauro Carvalho Chehab 	mantis->num		= devs;
17425aee3deSMauro Carvalho Chehab 	mantis->verbose		= verbose;
17525aee3deSMauro Carvalho Chehab 	mantis->pdev		= pdev;
176a96762daSJan Klötzke 	config			= drvdata->hwconfig;
17725aee3deSMauro Carvalho Chehab 	config->irq_handler	= &hopper_irq_handler;
17825aee3deSMauro Carvalho Chehab 	mantis->hwconfig	= config;
179a96762daSJan Klötzke 	mantis->rc_map_name	= drvdata->rc_map_name;
180a96762daSJan Klötzke 
181a96762daSJan Klötzke 	spin_lock_init(&mantis->intmask_lock);
18225aee3deSMauro Carvalho Chehab 
18325aee3deSMauro Carvalho Chehab 	err = mantis_pci_init(mantis);
18425aee3deSMauro Carvalho Chehab 	if (err) {
18525aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
18625aee3deSMauro Carvalho Chehab 		goto fail1;
18725aee3deSMauro Carvalho Chehab 	}
18825aee3deSMauro Carvalho Chehab 
18925aee3deSMauro Carvalho Chehab 	err = mantis_stream_control(mantis, STREAM_TO_HIF);
19025aee3deSMauro Carvalho Chehab 	if (err < 0) {
19125aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
19225aee3deSMauro Carvalho Chehab 		goto fail1;
19325aee3deSMauro Carvalho Chehab 	}
19425aee3deSMauro Carvalho Chehab 
19525aee3deSMauro Carvalho Chehab 	err = mantis_i2c_init(mantis);
19625aee3deSMauro Carvalho Chehab 	if (err < 0) {
19725aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
19825aee3deSMauro Carvalho Chehab 		goto fail2;
19925aee3deSMauro Carvalho Chehab 	}
20025aee3deSMauro Carvalho Chehab 
20125aee3deSMauro Carvalho Chehab 	err = mantis_get_mac(mantis);
20225aee3deSMauro Carvalho Chehab 	if (err < 0) {
20325aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
20425aee3deSMauro Carvalho Chehab 		goto fail2;
20525aee3deSMauro Carvalho Chehab 	}
20625aee3deSMauro Carvalho Chehab 
20725aee3deSMauro Carvalho Chehab 	err = mantis_dma_init(mantis);
20825aee3deSMauro Carvalho Chehab 	if (err < 0) {
20925aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
21025aee3deSMauro Carvalho Chehab 		goto fail3;
21125aee3deSMauro Carvalho Chehab 	}
21225aee3deSMauro Carvalho Chehab 
21325aee3deSMauro Carvalho Chehab 	err = mantis_dvb_init(mantis);
21425aee3deSMauro Carvalho Chehab 	if (err < 0) {
21525aee3deSMauro Carvalho Chehab 		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
21625aee3deSMauro Carvalho Chehab 		goto fail4;
21725aee3deSMauro Carvalho Chehab 	}
21825aee3deSMauro Carvalho Chehab 	devs++;
21925aee3deSMauro Carvalho Chehab 
22025aee3deSMauro Carvalho Chehab 	return err;
22125aee3deSMauro Carvalho Chehab 
22225aee3deSMauro Carvalho Chehab fail4:
22325aee3deSMauro Carvalho Chehab 	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err);
22425aee3deSMauro Carvalho Chehab 	mantis_dma_exit(mantis);
22525aee3deSMauro Carvalho Chehab 
22625aee3deSMauro Carvalho Chehab fail3:
22725aee3deSMauro Carvalho Chehab 	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err);
22825aee3deSMauro Carvalho Chehab 	mantis_i2c_exit(mantis);
22925aee3deSMauro Carvalho Chehab 
23025aee3deSMauro Carvalho Chehab fail2:
23125aee3deSMauro Carvalho Chehab 	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err);
23225aee3deSMauro Carvalho Chehab 	mantis_pci_exit(mantis);
23325aee3deSMauro Carvalho Chehab 
23425aee3deSMauro Carvalho Chehab fail1:
23525aee3deSMauro Carvalho Chehab 	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err);
23625aee3deSMauro Carvalho Chehab 	kfree(mantis);
23725aee3deSMauro Carvalho Chehab 
23825aee3deSMauro Carvalho Chehab fail0:
23925aee3deSMauro Carvalho Chehab 	return err;
24025aee3deSMauro Carvalho Chehab }
24125aee3deSMauro Carvalho Chehab 
2424c62e976SGreg Kroah-Hartman static void hopper_pci_remove(struct pci_dev *pdev)
24325aee3deSMauro Carvalho Chehab {
24425aee3deSMauro Carvalho Chehab 	struct mantis_pci *mantis = pci_get_drvdata(pdev);
24525aee3deSMauro Carvalho Chehab 
24625aee3deSMauro Carvalho Chehab 	if (mantis) {
24725aee3deSMauro Carvalho Chehab 		mantis_dvb_exit(mantis);
24825aee3deSMauro Carvalho Chehab 		mantis_dma_exit(mantis);
24925aee3deSMauro Carvalho Chehab 		mantis_i2c_exit(mantis);
25025aee3deSMauro Carvalho Chehab 		mantis_pci_exit(mantis);
25125aee3deSMauro Carvalho Chehab 		kfree(mantis);
25225aee3deSMauro Carvalho Chehab 	}
25325aee3deSMauro Carvalho Chehab 	return;
25425aee3deSMauro Carvalho Chehab 
25525aee3deSMauro Carvalho Chehab }
25625aee3deSMauro Carvalho Chehab 
2572b9e300fSArvind Yadav static const struct pci_device_id hopper_pci_table[] = {
258a96762daSJan Klötzke 	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config,
259a96762daSJan Klötzke 		   NULL),
26025aee3deSMauro Carvalho Chehab 	{ }
26125aee3deSMauro Carvalho Chehab };
26225aee3deSMauro Carvalho Chehab 
26325aee3deSMauro Carvalho Chehab MODULE_DEVICE_TABLE(pci, hopper_pci_table);
26425aee3deSMauro Carvalho Chehab 
26525aee3deSMauro Carvalho Chehab static struct pci_driver hopper_pci_driver = {
26625aee3deSMauro Carvalho Chehab 	.name		= DRIVER_NAME,
26725aee3deSMauro Carvalho Chehab 	.id_table	= hopper_pci_table,
26825aee3deSMauro Carvalho Chehab 	.probe		= hopper_pci_probe,
26925aee3deSMauro Carvalho Chehab 	.remove		= hopper_pci_remove,
27025aee3deSMauro Carvalho Chehab };
27125aee3deSMauro Carvalho Chehab 
272ecef5cc3SLibo Chen module_pci_driver(hopper_pci_driver);
27325aee3deSMauro Carvalho Chehab 
27425aee3deSMauro Carvalho Chehab MODULE_DESCRIPTION("HOPPER driver");
27525aee3deSMauro Carvalho Chehab MODULE_AUTHOR("Manu Abraham");
27625aee3deSMauro Carvalho Chehab MODULE_LICENSE("GPL");
277