⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hal_pci.c

📁 linux下的usb开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************************ * Philips ISP1362 hardware access layer driver for  * Intel X86 PCI platform * * (c) 2002 Koninklijke Philips Electronics N.V., All rights reserved *  * This  source code and any compilation or derivative thereof is the * proprietary information of Koninklijke Philips Electronics N.V. * and is confidential in nature. * Under no circumstances is this software to be exposed to or placed * under an Open Source License of any type without the expressed * written permission of Koninklijke Philips Electronics N.V. * * File Name:	hal_pci.c * * History:	 * *	Version	Date		Author		Comments * ------------------------------------------------- * 	1.0		09/23/02	SYARRA		Initial Creation * 	1.1		05/12/03	SYARRA		PLX9054-AC (PCI BRIDGE) Chip support * * Note: use tab space 4 ************************************************************************/#include <linux/config.h>#define MODULE#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/timer.h>#include <linux/list.h>#include <linux/interrupt.h>  /* for in_interrupt() */#undef DEBUG#include <linux/usb.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/unaligned.h>#include <asm/dma.h>#include "hal_intf.h"/*--------------------------------------------------------------* *               Local variable Definitions *--------------------------------------------------------------*/struct isp1362_dev 		isp1362_loc_dev[ISP1362_LAST_DEV];static	struct isp1362_hal	hal_data;static	__u16			pci_io_base  = 0;static	int   			isp1362_pci_latency;/*--------------------------------------------------------------* *               Local # Definitions *--------------------------------------------------------------*/#define		PCI_ACCESS_RETRY_COUNT	6#define		PLX_INT_CSR_REG		0x68#define		PLX_LBRD0_REG		0x18#define		PLX_LBRD0_WAIT_STATE_MASK	0x000000C3#define		PLX_LBRD0_WAIT_STATES		0x00000003#define		isp1362_driver_name	"1362-pci"#define		DRIVER_AUTHOR		"Philips Semiconductors"#define		DRIVER_DESC		"ISP1362 bus driver"/*--------------------------------------------------------------* *               Local Function Declerations *--------------------------------------------------------------*/static void __devexit isp1362_pci_remove (struct pci_dev *dev);static int __devinit isp1362_pci_probe (struct pci_dev *dev, 					const struct pci_device_id *id);static int isp1362_pci_suspend (struct pci_dev *dev, __u32 state);static int isp1362_pci_resume (struct pci_dev *dev);static void isp1362_pci_isr (int irq, void *__data, struct pt_regs *r);/*--------------------------------------------------------------* *               ISP1362 Interrupt Service Routine *--------------------------------------------------------------*//* Interrupt Service Routine of isp1362	                                   * Reads the source of interrupt and calls the corresponding driver's ISR. * Before calling the driver's ISR clears the source of interrupt. * The drivers can get the source of interrupt from the dev->int_reg field */void 	isp1362_pci_isr(int 	irq, void *__data, struct pt_regs *r) {	__u32		irq_mask;	__u32		hc_int_reg;	__u32		intrenable;	struct isp1362_dev	*dev;	func_debug(("isp1362_pci_isr(irq = %d,__data=%p,r=%p)\n",irq,__data,r))	/* Process the Host Controller Driver          */	dev = &isp1362_loc_dev[ISP1362_HC];	/* Get the source of interrupts for Host Controller          */	isp1362_reg_read16(dev, HC_MP_INT_REG,(dev->int_reg));	isp1362_reg_read16(dev, HC_MP_INT_EN_REG,irq_mask);	isp1362_reg_read32(dev, HC_INT_STS_REG,(dev->alt_int_reg) );	isp1362_reg_read32(dev, HC_INT_EN_REG,intrenable );		/* Clear the source of interrupts for Host Controller          */	isp1362_reg_write16(dev,(HC_MP_INT_REG|0x80), (dev->int_reg));	isp1362_reg_write32(dev,(HC_INT_STS_REG|0x80), (dev->alt_int_reg));	dev->int_reg &= irq_mask;	hc_int_reg = dev->int_reg;	dev->alt_int_reg &= intrenable;	/* call the Host Isr if any valid interrupt is present          */	if(dev->int_reg) dev->handler(dev,dev->isr_data);	/* Process OTG controller Driver 	 * Since OTG is part of  HC interrupt register, the interrupt source         * will be HC interrupt Register         */	dev = &isp1362_loc_dev[ISP1362_OTG];	if(hc_int_reg & HC_OTG_INT) {		/* Read the source of  OTG_INT and clear the                 * interrupt source                  */		isp1362_reg_read16(dev, OTG_INT_REG,(dev->int_reg));		isp1362_reg_write16(dev, (OTG_INT_REG|0x80),OTG_INT_MASK);			if(dev->int_reg) dev->handler(dev, dev->isr_data);	}	/* Process the Device Controller         */	dev = &isp1362_loc_dev[ISP1362_DC];	/* Get the source of interrupts for Device Controller 	 * Device Controller interrupts are cleared by the driver         * during processing         */	isp1362_reg_read32(dev, DC_INT_REG,(dev->int_reg));	isp1362_reg_read32(dev, DC_INT_EN_REG,irq_mask);	dev->int_reg &= irq_mask;	if(dev->int_reg) dev->handler(dev, dev->isr_data);	return;} /* End of isp1362_pci_isr *//*--------------------------------------------------------------* *               PCI Driver Interface Functions *--------------------------------------------------------------*/static const struct pci_device_id __devinitdata isp1362_pci_ids [] = {	{		/* handle PCI BRIDE  manufactured by PLX */		class:          ((PCI_CLASS_BRIDGE_OTHER << 8) | 0x00),		class_mask:     ~0,		/* no matter who makes it */		vendor:         PCI_VENDOR_ID_PLX,		device:         PCI_ANY_ID,		subvendor:      PCI_ANY_ID,		subdevice:      PCI_ANY_ID,	}, 	{ /* end: all zeroes */ }};MODULE_DEVICE_TABLE (pci, isp1362_pci_ids);/* Pci driver interface functions */static struct pci_driver isp1362_pci_driver = {		name:           "isp1362-hal",		id_table:       &isp1362_pci_ids [0],		probe:          isp1362_pci_probe,		remove:         isp1362_pci_remove,#ifdef  CONFIG_PM		suspend:        isp1362_pci_suspend,		resume:         isp1362_pci_resume,#endif  /* PM */};/* PCI probe function of ISP1362 * This function is called from PCI Driver as an initialization function * when it founds the PCI device. This functions initializes the information * for the 3 Controllers with the assigned resources and tests the register * access to these controllers and do a software reset and makes them ready * for the drivers to play with them. */static int __devinitisp1362_pci_probe (struct pci_dev *dev, const struct pci_device_id *id){	u8 latency, limit;	__u32	reg_data = 0;	int	retry_count;	struct isp1362_dev	*loc_dev;	__u8	 plx_lbrd0;	func_debug(("isp1362_pci_probe(dev=%p)\n",dev))		if (pci_enable_device(dev) < 0)		return -ENODEV;        if (!dev->irq) {        	detail_debug(("found ISP1362 device with no IRQ assigned. check BIOS settings!"))   	        return -ENODEV;        }		/* Grab the PLX PCI IO port start address         */	pci_io_base = pci_resource_start(dev, 1);	detail_debug(("isp1362 pci IO Base= %x\n", pci_io_base))	/* Get the Host Controller IO and INT resources	 */	loc_dev = &(isp1362_loc_dev[ISP1362_HC]);	loc_dev->irq = dev->irq;	reg_data = pci_resource_start(dev, 2);	loc_dev->io_base = reg_data;	loc_dev->io_data = loc_dev->io_base;	loc_dev->io_cmd = loc_dev->io_base + 2;	loc_dev->io_len = 4;	loc_dev->index = ISP1362_HC;	detail_debug(("isp1362 HC IO Base= %x irq = %x\n", loc_dev->io_base,loc_dev->irq))	/* Get the Device Controller IO and INT resources	 * Device controller also uses the same INT channel for PCI	 * but the IO is different	 */	loc_dev = &(isp1362_loc_dev[ISP1362_DC]);	loc_dev->irq = dev->irq;	loc_dev->io_base = reg_data + 4;	loc_dev->io_data = loc_dev->io_base;	loc_dev->io_cmd = loc_dev->io_base + 2;	loc_dev->io_len = 4;	loc_dev->index = ISP1362_DC;	detail_debug(("isp1362 DC IO Base= %x irq = %x\n", loc_dev->io_base,loc_dev->irq))	/* Get the OTG Controller IO and INT resources	 * OTG controller resources are same as Host Controller resources	 */	loc_dev = &(isp1362_loc_dev[ISP1362_OTG]);	loc_dev->irq = dev->irq;	loc_dev->io_base = reg_data;	loc_dev->io_data = loc_dev->io_base;	loc_dev->io_cmd = loc_dev->io_base + 2;	loc_dev->io_len = 4;	loc_dev->index = ISP1362_OTG;	detail_debug(("isp1362 OTG IO Base= %x irq = %x\n", loc_dev->io_base,loc_dev->irq))	/* bad pci latencies can contribute to overruns */ 	pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);	if (latency) {		pci_read_config_byte (dev, PCI_MAX_LAT, &limit);		if (limit && limit < latency) {			dbg ("PCI latency reduced to max %d", limit);			pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit);			isp1362_pci_latency = limit;		} else {			/* it might already have been reduced */			isp1362_pci_latency = latency;		}	}	/* Configure the Wait States for the PLX chip (needed for 9054-AC package) */	/* This is specific to ISP1362, PXL9054 bridge setting */	plx_lbrd0 = inb(PLX_LBRD0_REG + pci_io_base);	plx_lbrd0 &= PLX_LBRD0_WAIT_STATE_MASK;			/* Mask bits 5-2 Memory space 0 internal waut states */	plx_lbrd0 |= (PLX_LBRD0_WAIT_STATES << 2);	/* Set wait states to 3 */	outb(plx_lbrd0, (PLX_LBRD0_REG + pci_io_base));	/* Intialize Host Controller	 * Check IO resource availability, Check registers accebility	 * Read the Chip ID, Reset the chip and make it ready for use	 * by the Host Controller Driver          */	loc_dev = &(isp1362_loc_dev[ISP1362_HC]);	if( check_region(loc_dev->io_base, loc_dev->io_len) < 0) {		detail_debug(("Host Controller IO region (0x%x-0x%x) busy\n",loc_dev->io_base,loc_dev->io_len))		return -EBUSY;	}	request_region(loc_dev->io_base, loc_dev->io_len,isp1362_driver_name);	/* Try to check whether we can access Scratch Register of         * Host Controller or not. The initial PCI access is retried until          * local init for the PCI bridge is completed          */	retry_count = PCI_ACCESS_RETRY_COUNT;	while((reg_data != 0xFACE) && retry_count) {		isp1362_reg_write16(loc_dev, (HC_SCRATCH_REG|0x80), 0xFACE);		isp1362_reg_read16(loc_dev, HC_SCRATCH_REG,reg_data);		retry_count--;	}	/* Host Controller presence is detected by writing to scratch register	 * and reading back and checking the contents are same or not         */	if(reg_data != 0xFACE) {		detail_debug(("%s unable to access HC Scratch Register",isp1362_driver_name))		release_region(loc_dev->io_base, loc_dev->io_len);			return -ENODEV;	}	/* Reset the Host controller (reset requires some time .....         * is 100 msec ok??         */	loc_dev->active = 1;	isp1362_reg_write16(loc_dev, (HC_SW_RESET_REG|0x80), 0x00F6);	isp1362_mdelay(100);	isp1362_reg_read16(loc_dev, HC_CHIP_ID_REG,(loc_dev->chip_id));		detail_debug(("%s: found HC Chip Id = %x\n",isp1362_driver_name, loc_dev->chip_id))	release_region(loc_dev->io_base, loc_dev->io_len);/* release IO space */	/* Update the local and store the PCI data         */	hal_data.io_usage = 0;	hal_data.irq_usage = 0;	pci_set_drvdata (dev, isp1362_loc_dev);	/* Now Process the Device Controller 	 */	loc_dev = &(isp1362_loc_dev[ISP1362_DC]);	request_region(loc_dev->io_base, loc_dev->io_len,isp1362_driver_name);	reg_data = 0;	isp1362_reg_write16(loc_dev, (DC_SCRATCH_REG&0xFE), 0xFACE);	isp1362_reg_read16(loc_dev, DC_SCRATCH_REG,reg_data);	if(reg_data != 0xFACE) {		detail_debug(("%s unable to access DC Scratch Register",isp1362_driver_name))		release_region(loc_dev->io_base, loc_dev->io_len);		return -ENODEV;	}	loc_dev->active = 1;	isp1362_reg_read16(loc_dev, DC_CHIP_ID_REG,(loc_dev->chip_id));	detail_debug(("%s: found DC Chip Id = %x\n",isp1362_driver_name, loc_dev->chip_id))	/* Rest the DC. Assume 10 msec are fairly enough for DC to reset	 */	isp1362_command(DC_SW_RESET_REG,loc_dev);	isp1362_mdelay(10);	release_region(loc_dev->io_base, loc_dev->io_len);/* release IO space */	/* Now Process the OTG Controller 	 * OTG resources are same as HC resource nothing to be done here	 */	loc_dev = &(isp1362_loc_dev[ISP1362_OTG]);	loc_dev->active = 1;	return 0;} /* End of isp1362_pci_probe */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -