static int __init sgi_button_devinit(void)
{
	if (ip22_is_fullhouse())
		return 0; /*                                  */

	return IS_ERR(platform_device_register_simple("sgibtns", -1, NULL, 0));
}
Ejemplo n.º 2
0
int __init ip22_gio_init(void)
{
	unsigned int pbdma __maybe_unused;
	int ret;

	ret = device_register(&gio_bus);
	if (ret) {
		put_device(&gio_bus);
		return ret;
	}

	ret = bus_register(&gio_bus_type);
	if (!ret) {
		request_resource(&iomem_resource, &gio_bus_resource);
		printk(KERN_INFO "GIO: Probing bus...\n");

		if (ip22_is_fullhouse()) {
			/* Indigo2 */
			ip22_check_gio(0, GIO_SLOT_GFX_BASE, SGI_GIO_1_IRQ);
			ip22_check_gio(1, GIO_SLOT_EXP0_BASE, SGI_GIO_1_IRQ);
		} else {
			/* Indy/Challenge S */
			if (get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1]))
				ip22_check_gio(0, GIO_SLOT_GFX_BASE,
					       SGI_GIO_0_IRQ);
			ip22_check_gio(1, GIO_SLOT_EXP0_BASE, SGI_GIOEXP0_IRQ);
			ip22_check_gio(2, GIO_SLOT_EXP1_BASE, SGI_GIOEXP1_IRQ);
		}
	} else
		device_unregister(&gio_bus);

	return ret;
}
Ejemplo n.º 3
0
void __init sgihpc_init(void)
{
	/* ioremap can't fail */
	hpc3c0 = (struct hpc3_regs *)
		 ioremap(HPC3_CHIP0_BASE, sizeof(struct hpc3_regs));
	hpc3c1 = (struct hpc3_regs *)
		 ioremap(HPC3_CHIP1_BASE, sizeof(struct hpc3_regs));
	/* IOC lives in PBUS PIO channel 6 */
	sgioc = (struct sgioc_regs *)hpc3c0->pbus_extregs[6];

	hpc3c0->pbus_piocfg[6][0] |= HPC3_PIOCFG_DS16;
	if (ip22_is_fullhouse()) {
		/* Full House comes with INT2 which lives in PBUS PIO
		 * channel 4 */
		sgint = (struct sgint_regs *)hpc3c0->pbus_extregs[4];
		system_type = "SGI Indigo2";
	} else {
		/* Guiness comes with INT3 which is part of IOC */
		sgint = &sgioc->int3;
		system_type = "SGI Indy";
	}

	sgi_ioc_reset = (SGIOC_RESET_PPORT | SGIOC_RESET_KBDMOUSE |
			 SGIOC_RESET_EISA | SGIOC_RESET_ISDN |
			 SGIOC_RESET_LC0OFF);

	sgi_ioc_write = (SGIOC_WRITE_EASEL | SGIOC_WRITE_NTHRESH |
			 SGIOC_WRITE_TPSPEED | SGIOC_WRITE_EPSEL |
			 SGIOC_WRITE_U0AMODE | SGIOC_WRITE_U1AMODE);

	sgioc->reset = sgi_ioc_reset;
	sgioc->write = sgi_ioc_write;
}
Ejemplo n.º 4
0
/*
 * Read specified register from main NVRAM
 */
unsigned short ip22_nvram_read(int reg)
{
	if (ip22_is_fullhouse())
		/* IP22 (Indigo2 aka FullHouse) stores env variables into
		 * 93CS56 Microwire Bus EEPROM 2048 Bit (128x16) */
		return ip22_eeprom_read(&hpc3c0->eeprom, reg);
	else {
		unsigned short tmp;
		/* IP24 (Indy aka Guiness) uses DS1386 8K version */
		reg <<= 1;
		tmp = hpc3c0->bbram[reg++] & 0xff;
		return (tmp << 8) | (hpc3c0->bbram[reg] & 0xff);
	}
}
Ejemplo n.º 5
0
unsigned short ip22_nvram_read(int reg)
{
	if (ip22_is_fullhouse())
		/*                                                       
                                                   */
		return ip22_eeprom_read(&hpc3c0->eeprom, reg);
	else {
		unsigned short tmp;
		/*                                                */
		reg <<= 1;
		tmp = hpc3c0->bbram[reg++] & 0xff;
		return (tmp << 8) | (hpc3c0->bbram[reg] & 0xff);
	}
}
Ejemplo n.º 6
0
/*
 * Here we need to calibrate the cycle counter to at least be close.
 */
__init void plat_time_init(void)
{
	unsigned long r4k_ticks[3];
	unsigned long r4k_tick;

	/*
	 * Figure out the r4k offset, the algorithm is very simple and works in
	 * _all_ cases as long as the 8254 counter register itself works ok (as
	 * an interrupt driving timer it does not because of bug, this is why
	 * we are using the onchip r4k counter/compare register to serve this
	 * purpose, but for r4k_offset calculation it will work ok for us).
	 * There are other very complicated ways of performing this calculation
	 * but this one works just fine so I am not going to futz around. ;-)
	 */
	printk(KERN_INFO "Calibrating system timer... ");
	dosample();	/* Prime cache. */
	dosample();	/* Prime cache. */
	/* Zero is NOT an option. */
	do {
		r4k_ticks[0] = dosample();
	} while (!r4k_ticks[0]);
	do {
		r4k_ticks[1] = dosample();
	} while (!r4k_ticks[1]);

	if (r4k_ticks[0] != r4k_ticks[1]) {
		printk("warning: timer counts differ, retrying... ");
		r4k_ticks[2] = dosample();
		if (r4k_ticks[2] == r4k_ticks[0]
		    || r4k_ticks[2] == r4k_ticks[1])
			r4k_tick = r4k_ticks[2];
		else {
			printk("disagreement, using average... ");
			r4k_tick = (r4k_ticks[0] + r4k_ticks[1]
				   + r4k_ticks[2]) / 3;
		}
	} else
		r4k_tick = r4k_ticks[0];

	printk("%d [%d.%04d MHz CPU]\n", (int) r4k_tick,
		(int) (r4k_tick / (500000 / HZ)),
		(int) (r4k_tick % (500000 / HZ)));

	mips_hpt_frequency = r4k_tick * HZ;

	if (ip22_is_fullhouse())
		setup_pit_timer();
}
Ejemplo n.º 7
0
/*
 * Create a platform device for the GPI port that receives the
 * image data from the embedded camera.
 */
static int __init sgiwd93_devinit(void)
{
    int res;

    sgiwd93_0_pd.hregs    = &hpc3c0->scsi_chan0;
    sgiwd93_0_pd.wdregs    = (unsigned char *) hpc3c0->scsi0_ext;

    res = platform_device_register(&sgiwd93_0_device);
    if (res)
        return res;

    if (!ip22_is_fullhouse())
        return 0;

    sgiwd93_1_pd.hregs    = &hpc3c0->scsi_chan1;
    sgiwd93_1_pd.wdregs    = (unsigned char *) hpc3c0->scsi1_ext;

    return platform_device_register(&sgiwd93_1_device);
}
Ejemplo n.º 8
0
/*
 * Create a platform device for the GPI port that receives the
 * image data from the embedded camera.
 */
static int __init sgiseeq_devinit(void)
{
    unsigned int tmp;
    int res, i;

    eth0_pd.hpc = hpc3c0;
    eth0_pd.irq = SGI_ENET_IRQ;
#define EADDR_NVOFS     250
    for (i = 0; i < 3; i++) {
        unsigned short tmp = ip22_nvram_read(EADDR_NVOFS / 2 + i);

        eth0_pd.mac[2 * i]     = tmp >> 8;
        eth0_pd.mac[2 * i + 1] = tmp & 0xff;
    }

    res = platform_device_register(&eth0_device);
    if (res)
        return res;

    /* Second HPC is missing? */
    if (!ip22_is_fullhouse() ||
        get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]))
        return 0;

    sgimc->giopar |= SGIMC_GIOPAR_MASTEREXP1 | SGIMC_GIOPAR_EXP164 |
                     SGIMC_GIOPAR_HPC264;
    hpc3c1->pbus_piocfg[0][0] = 0x3ffff;
    /* interrupt/config register on Challenge S Mezz board */
    hpc3c1->pbus_extregs[0][0] = 0x30;

    eth1_pd.hpc = hpc3c1;
    eth1_pd.irq = SGI_GIO_0_IRQ;
#define EADDR_NVOFS     250
    for (i = 0; i < 3; i++) {
        unsigned short tmp = ip22_eeprom_read(&hpc3c1->eeprom,
                                              EADDR_NVOFS / 2 + i);

        eth1_pd.mac[2 * i]     = tmp >> 8;
        eth1_pd.mac[2 * i + 1] = tmp & 0xff;
    }

    return platform_device_register(&eth1_device);
}
Ejemplo n.º 9
0
static irqreturn_t panel_int(int irq, void *dev_id, struct pt_regs *regs)
{
	unsigned int buttons;

	buttons = sgioc->panel;
	sgioc->panel = SGIOC_PANEL_POWERON | SGIOC_PANEL_POWERINTR;

	if (sgint->istat1 & SGINT_ISTAT1_PWR) {
		/* Wait until interrupt goes away */
		disable_irq(SGI_PANEL_IRQ);
		init_timer(&debounce_timer);
		debounce_timer.function = debounce;
		debounce_timer.expires = jiffies + 5;
		add_timer(&debounce_timer);
	}

	/* Power button was pressed 
	 * ioc.ps page 22: "The Panel Register is called Power Control by Full
	 * House. Only lowest 2 bits are used. Guiness uses upper four bits
	 * for volume control". This is not true, all bits are pulled high
	 * on fullhouse */
	if (ip22_is_fullhouse() || !(buttons & SGIOC_PANEL_POWERINTR)) {
		power_button();
		return IRQ_HANDLED;
	}
	/* TODO: mute/unmute */
	/* Volume up button was pressed */
	if (!(buttons & SGIOC_PANEL_VOLUPINTR)) {
		init_timer(&volume_timer);
		volume_timer.function = volume_up_button;
		volume_timer.expires = jiffies + 1;
		add_timer(&volume_timer);
	}
	/* Volume down button was pressed */
	if (!(buttons & SGIOC_PANEL_VOLDNINTR)) {
		init_timer(&volume_timer);
		volume_timer.function = volume_down_button;
		volume_timer.expires = jiffies + 1;
		add_timer(&volume_timer);
	}

	return IRQ_HANDLED;
}
Ejemplo n.º 10
0
void __init arch_init_irq(void)
{
    int i;

    /* Init local mask --> irq tables. */
    for (i = 0; i < 256; i++) {
        if (i & 0x80) {
            lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 7;
            lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 7;
            lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 7;
            lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 7;
        } else if (i & 0x40) {
            lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 6;
            lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 6;
            lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 6;
            lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 6;
        } else if (i & 0x20) {
            lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 5;
            lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 5;
            lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 5;
            lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 5;
        } else if (i & 0x10) {
            lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 4;
            lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 4;
            lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 4;
            lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 4;
        } else if (i & 0x08) {
            lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 3;
            lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 3;
            lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 3;
            lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 3;
        } else if (i & 0x04) {
            lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 2;
            lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 2;
            lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 2;
            lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 2;
        } else if (i & 0x02) {
            lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 1;
            lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 1;
            lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 1;
            lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 1;
        } else if (i & 0x01) {
            lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 0;
            lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 0;
            lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 0;
            lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 0;
        } else {
            lc0msk_to_irqnr[i] = 0;
            lc1msk_to_irqnr[i] = 0;
            lc2msk_to_irqnr[i] = 0;
            lc3msk_to_irqnr[i] = 0;
        }
    }

    /* Mask out all interrupts. */
    sgint->imask0 = 0;
    sgint->imask1 = 0;
    sgint->cmeimask0 = 0;
    sgint->cmeimask1 = 0;

    /* init CPU irqs */
    mips_cpu_irq_init();

    for (i = SGINT_LOCAL0; i < SGI_INTERRUPTS; i++) {
        struct irq_chip *handler;

        if (i < SGINT_LOCAL1)
            handler        = &ip22_local0_irq_type;
        else if (i < SGINT_LOCAL2)
            handler        = &ip22_local1_irq_type;
        else if (i < SGINT_LOCAL3)
            handler        = &ip22_local2_irq_type;
        else
            handler        = &ip22_local3_irq_type;

        set_irq_chip_and_handler(i, handler, handle_level_irq);
    }

    /* vector handler. this register the IRQ as non-sharable */
    setup_irq(SGI_LOCAL_0_IRQ, &local0_cascade);
    setup_irq(SGI_LOCAL_1_IRQ, &local1_cascade);
    setup_irq(SGI_BUSERR_IRQ, &buserr);

    /* cascade in cascade. i love Indy ;-) */
    setup_irq(SGI_MAP_0_IRQ, &map0_cascade);
#ifdef USE_LIO3_IRQ
    setup_irq(SGI_MAP_1_IRQ, &map1_cascade);
#endif

#ifdef CONFIG_EISA
    if (ip22_is_fullhouse())    /* Only Indigo-2 has EISA stuff */
            ip22_eisa_init();
#endif
}
Ejemplo n.º 11
0
Archivo: ip22-mc.c Proyecto: 12zz/linux
void __init sgimc_init(void)
{
	u32 tmp;

	/* ioremap can't fail */
	sgimc = (struct sgimc_regs *)
		ioremap(SGIMC_BASE, sizeof(struct sgimc_regs));

	printk(KERN_INFO "MC: SGI memory controller Revision %d\n",
	       (int) sgimc->systemid & SGIMC_SYSID_MASKREV);

	/* Place the MC into a known state.  This must be done before
	 * interrupts are first enabled etc.
	 */

	/* Step 0: Make sure we turn off the watchdog in case it's
	 *	   still running (which might be the case after a
	 *	   soft reboot).
	 */
	tmp = sgimc->cpuctrl0;
	tmp &= ~SGIMC_CCTRL0_WDOG;
	sgimc->cpuctrl0 = tmp;

	/* Step 1: The CPU/GIO error status registers will not latch
	 *	   up a new error status until the register has been
	 *	   cleared by the cpu.	These status registers are
	 *	   cleared by writing any value to them.
	 */
	sgimc->cstat = sgimc->gstat = 0;

	/* Step 2: Enable all parity checking in cpu control register
	 *	   zero.
	 */
	/* don't touch parity settings for IP28 */
	tmp = sgimc->cpuctrl0;
#ifndef CONFIG_SGI_IP28
	tmp |= SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM;
#endif
	tmp |= SGIMC_CCTRL0_R4KNOCHKPARR;
	sgimc->cpuctrl0 = tmp;

	/* Step 3: Setup the MC write buffer depth, this is controlled
	 *	   in cpu control register 1 in the lower 4 bits.
	 */
	tmp = sgimc->cpuctrl1;
	tmp &= ~0xf;
	tmp |= 0xd;
	sgimc->cpuctrl1 = tmp;

	/* Step 4: Initialize the RPSS divider register to run as fast
	 *	   as it can correctly operate.	 The register is laid
	 *	   out as follows:
	 *
	 *	   ----------------------------------------
	 *	   |  RESERVED	|   INCREMENT	| DIVIDER |
	 *	   ----------------------------------------
	 *	    31	      16 15	       8 7	 0
	 *
	 *	   DIVIDER determines how often a 'tick' happens,
	 *	   INCREMENT determines by how the RPSS increment
	 *	   registers value increases at each 'tick'. Thus,
	 *	   for IP22 we get INCREMENT=1, DIVIDER=1 == 0x101
	 */
	sgimc->divider = 0x101;

	/* Step 5: Initialize GIO64 arbitrator configuration register.
	 *
	 * NOTE: HPC init code in sgihpc_init() must run before us because
	 *	 we need to know Guiness vs. FullHouse and the board
	 *	 revision on this machine. You have been warned.
	 */

	/* First the basic invariants across all GIO64 implementations. */
	tmp = sgimc->giopar & SGIMC_GIOPAR_GFX64; /* keep gfx 64bit settings */
	tmp |= SGIMC_GIOPAR_HPC64;	/* All 1st HPC's interface at 64bits */
	tmp |= SGIMC_GIOPAR_ONEBUS;	/* Only one physical GIO bus exists */

	if (ip22_is_fullhouse()) {
		/* Fullhouse specific settings. */
		if (SGIOC_SYSID_BOARDREV(sgioc->sysid) < 2) {
			tmp |= SGIMC_GIOPAR_HPC264;	/* 2nd HPC at 64bits */
			tmp |= SGIMC_GIOPAR_PLINEEXP0;	/* exp0 pipelines */
			tmp |= SGIMC_GIOPAR_MASTEREXP1; /* exp1 masters */
			tmp |= SGIMC_GIOPAR_RTIMEEXP0;	/* exp0 is realtime */
		} else {
			tmp |= SGIMC_GIOPAR_HPC264;	/* 2nd HPC 64bits */
			tmp |= SGIMC_GIOPAR_PLINEEXP0;	/* exp[01] pipelined */
			tmp |= SGIMC_GIOPAR_PLINEEXP1;
			tmp |= SGIMC_GIOPAR_MASTEREISA; /* EISA masters */
		}
	} else {
		/* Guiness specific settings. */
		tmp |= SGIMC_GIOPAR_EISA64;	/* MC talks to EISA at 64bits */
		tmp |= SGIMC_GIOPAR_MASTEREISA; /* EISA bus can act as master */
	}
	sgimc->giopar = tmp;	/* poof */

	probe_memory();
}
Ejemplo n.º 12
0
void __init init_IRQ(void)
{
	int i;

	/* Init local mask --> irq tables. */
	for (i = 0; i < 256; i++) {
		if (i & 0x80) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 7;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 7;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 7;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 7;
		} else if (i & 0x40) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 6;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 6;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 6;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 6;
		} else if (i & 0x20) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 5;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 5;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 5;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 5;
		} else if (i & 0x10) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 4;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 4;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 4;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 4;
		} else if (i & 0x08) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 3;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 3;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 3;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 3;
		} else if (i & 0x04) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 2;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 2;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 2;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 2;
		} else if (i & 0x02) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 1;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 1;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 1;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 1;
		} else if (i & 0x01) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 0;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 0;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 0;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 0;
		} else {
			lc0msk_to_irqnr[i] = 0;
			lc1msk_to_irqnr[i] = 0;
			lc2msk_to_irqnr[i] = 0;
			lc3msk_to_irqnr[i] = 0;
		}
	}

	/* Mask out all interrupts. */
	sgint->imask0 = 0;
	sgint->imask1 = 0;
	sgint->cmeimask0 = 0;
	sgint->cmeimask1 = 0;

	set_except_vector(0, indyIRQ);

	init_generic_irq();
	/* init CPU irqs */
	mips_cpu_irq_init(SGINT_CPU);

	for (i = SGINT_LOCAL0; i < SGI_INTERRUPTS; i++) {
		hw_irq_controller *handler;

		if (i < SGINT_LOCAL1)
			handler		= &ip22_local0_irq_type;
		else if (i < SGINT_LOCAL2)
			handler		= &ip22_local1_irq_type;
		else if (i < SGINT_LOCAL3)
			handler		= &ip22_local2_irq_type;
		else
			handler		= &ip22_local3_irq_type;

		irq_desc[i].status	= IRQ_DISABLED;
		irq_desc[i].action	= 0;
		irq_desc[i].depth	= 1;
		irq_desc[i].handler	= handler;
	}

	/* vector handler. this register the IRQ as non-sharable */
	setup_irq(SGI_LOCAL_0_IRQ, &local0_cascade);
	setup_irq(SGI_LOCAL_1_IRQ, &local1_cascade);
	setup_irq(SGI_BUSERR_IRQ, &buserr);

	/* cascade in cascade. i love Indy ;-) */
	setup_irq(SGI_MAP_0_IRQ, &map0_cascade);
#ifdef USE_LIO3_IRQ
	setup_irq(SGI_MAP_1_IRQ, &map1_cascade);
#endif

#ifdef CONFIG_EISA
	if (ip22_is_fullhouse())	/* Only Indigo-2 has EISA stuff */
	        ip22_eisa_init ();
#endif
}
Ejemplo n.º 13
0
static int __init vino_init(void)
{
	unsigned long rev;
	dma_addr_t dma;
	int i, ret = 0;
	
	/* VINO is Indy specific beast */
	if (ip22_is_fullhouse())
		return -ENODEV;

	/*
	 * VINO is in the EISA address space, so the sysid register will tell
	 * us if the EISA_PRESENT pin on MC has been pulled low.
	 * 
	 * If EISA_PRESENT is not set we definitely don't have a VINO equiped
	 * system.
	 */
	if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
		printk(KERN_ERR "VINO not found\n");
		return -ENODEV;
	}

	vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
	if (!vino)
		return -EIO;

	/* Okay, once we know that VINO is present we'll read its revision
	 * safe way. One never knows... */
	if (get_dbe(rev, &(vino->rev_id))) {
		printk(KERN_ERR "VINO: failed to read revision register\n");
		ret = -ENODEV;
		goto out_unmap;
	}
	if (VINO_ID_VALUE(rev) != VINO_CHIP_ID) {
		printk(KERN_ERR "VINO is not VINO (Rev/ID: 0x%04lx)\n", rev);
		ret = -ENODEV;
		goto out_unmap;
	}
	printk(KERN_INFO "VINO Rev: 0x%02lx\n", VINO_REV_NUM(rev));

	Vino = (struct vino_video *)
		kmalloc(sizeof(struct vino_video), GFP_KERNEL);
	if (!Vino) {
		ret = -ENOMEM;
		goto out_unmap;
	}
	memset(Vino, 0, sizeof(struct vino_video));

	Vino->dummy_desc = get_zeroed_page(GFP_KERNEL | GFP_DMA);
	if (!Vino->dummy_desc) {
		ret = -ENOMEM;
		goto out_free_vino;
	}
	Vino->dummy_dma.cpu = pci_alloc_consistent(NULL, 4 * sizeof(dma_addr_t),
						   &Vino->dummy_dma.dma);
	if (!Vino->dummy_dma.cpu) {
		ret = -ENOMEM;
		goto out_free_dummy_desc;
	}
	dma = pci_map_single(NULL, (void *)Vino->dummy_desc, PAGE_SIZE,
			     PCI_DMA_FROMDEVICE);
	for (i = 0; i < 4; i++)
		Vino->dummy_dma.cpu[i] = dma;

	vino->control = 0;
	/* prevent VINO from throwing spurious interrupts */
	vino->a.next_4_desc = Vino->dummy_dma.dma;
	vino->b.next_4_desc = Vino->dummy_dma.dma;
	udelay(5);
	vino->intr_status = 0;
        /* set threshold level */
        vino->a.fifo_thres = threshold_a;
	vino->b.fifo_thres = threshold_b;

	spin_lock_init(&Vino->vino_lock);
	spin_lock_init(&Vino->input_lock);
	init_channel_data(&Vino->chA, VINO_CHAN_A);
	init_channel_data(&Vino->chB, VINO_CHAN_B);

	if (request_irq(SGI_VINO_IRQ, vino_interrupt, 0, vinostr, NULL)) {
		printk(KERN_ERR "VINO: request irq%02d failed\n",
		       SGI_VINO_IRQ);
		ret = -EAGAIN;
		goto out_unmap_dummy_desc;
	}

	ret = vino_i2c_add_bus();
	if (ret) {
		printk(KERN_ERR "VINO: I2C bus registration failed\n");
		goto out_free_irq;
	}

	if (video_register_device(&Vino->chA.vdev, VFL_TYPE_GRABBER, -1) < 0) {
		printk("%s, chnl %d: device registration failed.\n",
			Vino->chA.vdev.name, Vino->chA.chan);
		ret = -EINVAL;
		goto out_i2c_del_bus;
	}
	if (video_register_device(&Vino->chB.vdev, VFL_TYPE_GRABBER, -1) < 0) {
		printk("%s, chnl %d: device registration failed.\n",
			Vino->chB.vdev.name, Vino->chB.chan);
		ret = -EINVAL;
		goto out_unregister_vdev;
	}

#if defined(CONFIG_KMOD) && defined (MODULE)
	request_module("saa7191");
	request_module("indycam");
#endif
	return 0;

out_unregister_vdev:
	video_unregister_device(&Vino->chA.vdev);
out_i2c_del_bus:
	vino_i2c_del_bus();
out_free_irq:
	free_irq(SGI_VINO_IRQ, NULL);
out_unmap_dummy_desc:
	pci_unmap_single(NULL, Vino->dummy_dma.dma, PAGE_SIZE,
			 PCI_DMA_FROMDEVICE);
	pci_free_consistent(NULL, 4 * sizeof(dma_addr_t),
			    (void *)Vino->dummy_dma.cpu, Vino->dummy_dma.dma);
out_free_dummy_desc:
	free_page(Vino->dummy_desc);
out_free_vino:
	kfree(Vino);
out_unmap:
	iounmap(vino);

	return ret;
}
Ejemplo n.º 14
0
void __init arch_init_irq(void)
{
	int i;

	
	for (i = 0; i < 256; i++) {
		if (i & 0x80) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 7;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 7;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 7;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 7;
		} else if (i & 0x40) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 6;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 6;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 6;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 6;
		} else if (i & 0x20) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 5;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 5;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 5;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 5;
		} else if (i & 0x10) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 4;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 4;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 4;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 4;
		} else if (i & 0x08) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 3;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 3;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 3;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 3;
		} else if (i & 0x04) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 2;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 2;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 2;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 2;
		} else if (i & 0x02) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 1;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 1;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 1;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 1;
		} else if (i & 0x01) {
			lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 0;
			lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 0;
			lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 0;
			lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 0;
		} else {
			lc0msk_to_irqnr[i] = 0;
			lc1msk_to_irqnr[i] = 0;
			lc2msk_to_irqnr[i] = 0;
			lc3msk_to_irqnr[i] = 0;
		}
	}

	
	sgint->imask0 = 0;
	sgint->imask1 = 0;
	sgint->cmeimask0 = 0;
	sgint->cmeimask1 = 0;

	
	mips_cpu_irq_init();

	for (i = SGINT_LOCAL0; i < SGI_INTERRUPTS; i++) {
		struct irq_chip *handler;

		if (i < SGINT_LOCAL1)
			handler		= &ip22_local0_irq_type;
		else if (i < SGINT_LOCAL2)
			handler		= &ip22_local1_irq_type;
		else if (i < SGINT_LOCAL3)
			handler		= &ip22_local2_irq_type;
		else
			handler		= &ip22_local3_irq_type;

		irq_set_chip_and_handler(i, handler, handle_level_irq);
	}

	
	setup_irq(SGI_LOCAL_0_IRQ, &local0_cascade);
	setup_irq(SGI_LOCAL_1_IRQ, &local1_cascade);
	setup_irq(SGI_BUSERR_IRQ, &buserr);

	
	setup_irq(SGI_MAP_0_IRQ, &map0_cascade);
#ifdef USE_LIO3_IRQ
	setup_irq(SGI_MAP_1_IRQ, &map1_cascade);
#endif

#ifdef CONFIG_EISA
	if (ip22_is_fullhouse())	
		ip22_eisa_init();
#endif
}