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

📄 isp116x-hcd.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (!list_empty(&isp116x->async))		seq_printf(s, "\n");	seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE);	for (i = 0; i < PERIODIC_SIZE; i++) {		ep = isp116x->periodic[i];		if (!ep)			continue;		seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]);		/* DUMB: prints shared entries multiple times */		do {			seq_printf(s, "   %d/%p (%sdev%d ep%d%s max %d)\n",				   ep->period, ep,				   (ep->udev->speed ==				    USB_SPEED_FULL) ? "" : "ls ",				   ep->udev->devnum, ep->epnum,				   (ep->epnum ==				    0) ? "" : ((ep->nextpid ==						USB_PID_IN) ? "in" : "out"),				   ep->maxpacket);			ep = ep->next;		} while (ep);	}	spin_unlock_irq(&isp116x->lock);	seq_printf(s, "\n");	return 0;}static int proc_isp116x_open(struct inode *inode, struct file *file){	return single_open(file, proc_isp116x_show, PDE(inode)->data);}static struct file_operations proc_ops = {	.open = proc_isp116x_open,	.read = seq_read,	.llseek = seq_lseek,	.release = single_release,};/* expect just one isp116x per system */static const char proc_filename[] = "driver/isp116x";static void create_debug_file(struct isp116x *isp116x){	struct proc_dir_entry *pde;	pde = create_proc_entry(proc_filename, 0, NULL);	if (pde == NULL)		return;	pde->proc_fops = &proc_ops;	pde->data = isp116x;	isp116x->pde = pde;}static void remove_debug_file(struct isp116x *isp116x){	if (isp116x->pde)		remove_proc_entry(proc_filename, NULL);}#endif/*-----------------------------------------------------------------*//*  Software reset - can be called from any contect.*/static int isp116x_sw_reset(struct isp116x *isp116x){	int retries = 15;	unsigned long flags;	int ret = 0;	spin_lock_irqsave(&isp116x->lock, flags);	isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC);	isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR);	while (--retries) {		/* It usually resets within 1 ms */		mdelay(1);		if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR))			break;	}	if (!retries) {		ERR("Software reset timeout\n");		ret = -ETIME;	}	spin_unlock_irqrestore(&isp116x->lock, flags);	return ret;}static int isp116x_reset(struct usb_hcd *hcd){	struct isp116x *isp116x = hcd_to_isp116x(hcd);	unsigned long t;	u16 clkrdy = 0;	int ret = 0, timeout = 15 /* ms */ ;	ret = isp116x_sw_reset(isp116x);	if (ret)		return ret;	t = jiffies + msecs_to_jiffies(timeout);	while (time_before_eq(jiffies, t)) {		msleep(4);		spin_lock_irq(&isp116x->lock);		clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY;		spin_unlock_irq(&isp116x->lock);		if (clkrdy)			break;	}	if (!clkrdy) {		ERR("Clock not ready after 20ms\n");		/* After sw_reset the clock won't report to be ready, if		   H_WAKEUP pin is high. */		ERR("Please make sure that the H_WAKEUP pin is pulled low!\n");		ret = -ENODEV;	}	return ret;}static void isp116x_stop(struct usb_hcd *hcd){	struct isp116x *isp116x = hcd_to_isp116x(hcd);	unsigned long flags;	u32 val;	spin_lock_irqsave(&isp116x->lock, flags);	isp116x_write_reg16(isp116x, HCuPINTENB, 0);	/* Switch off ports' power, some devices don't come up	   after next 'insmod' without this */	val = isp116x_read_reg32(isp116x, HCRHDESCA);	val &= ~(RH_A_NPS | RH_A_PSM);	isp116x_write_reg32(isp116x, HCRHDESCA, val);	isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS);	spin_unlock_irqrestore(&isp116x->lock, flags);	isp116x_sw_reset(isp116x);}/*  Configure the chip. The chip must be successfully reset by now.*/static int isp116x_start(struct usb_hcd *hcd){	struct isp116x *isp116x = hcd_to_isp116x(hcd);	struct isp116x_platform_data *board = isp116x->board;	u32 val;	unsigned long flags;	spin_lock_irqsave(&isp116x->lock, flags);	/* clear interrupt status and disable all interrupt sources */	isp116x_write_reg16(isp116x, HCuPINT, 0xff);	isp116x_write_reg16(isp116x, HCuPINTENB, 0);	val = isp116x_read_reg16(isp116x, HCCHIPID);	if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC) {		ERR("Invalid chip ID %04x\n", val);		spin_unlock_irqrestore(&isp116x->lock, flags);		return -ENODEV;	}	/* To be removed in future */	hcd->uses_new_polling = 1;	isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE);	isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE);	/* ----- HW conf */	val = HCHWCFG_INT_ENABLE | HCHWCFG_DBWIDTH(1);	if (board->sel15Kres)		val |= HCHWCFG_15KRSEL;	/* Remote wakeup won't work without working clock */	if (board->remote_wakeup_enable)		val |= HCHWCFG_CLKNOTSTOP;	if (board->oc_enable)		val |= HCHWCFG_ANALOG_OC;	if (board->int_act_high)		val |= HCHWCFG_INT_POL;	if (board->int_edge_triggered)		val |= HCHWCFG_INT_TRIGGER;	isp116x_write_reg16(isp116x, HCHWCFG, val);	/* ----- Root hub conf */	val = (25 << 24) & RH_A_POTPGT;	/* AN10003_1.pdf recommends RH_A_NPS (no power switching) to	   be always set. Yet, instead, we request individual port	   power switching. */	val |= RH_A_PSM;	/* Report overcurrent per port */	val |= RH_A_OCPM;	isp116x_write_reg32(isp116x, HCRHDESCA, val);	isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA);	val = RH_B_PPCM;	isp116x_write_reg32(isp116x, HCRHDESCB, val);	isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB);	val = 0;	if (board->remote_wakeup_enable) {		hcd->can_wakeup = 1;		val |= RH_HS_DRWE;	}	isp116x_write_reg32(isp116x, HCRHSTATUS, val);	isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);	isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf);	hcd->state = HC_STATE_RUNNING;	/* Set up interrupts */	isp116x->intenb = HCINT_MIE | HCINT_RHSC | HCINT_UE;	if (board->remote_wakeup_enable)		isp116x->intenb |= HCINT_RD;	isp116x->irqenb = HCuPINT_ATL | HCuPINT_OPR;	/* | HCuPINT_SUSP; */	isp116x_write_reg32(isp116x, HCINTENB, isp116x->intenb);	isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);	/* Go operational */	val = HCCONTROL_USB_OPER;	if (board->remote_wakeup_enable)		val |= HCCONTROL_RWE;	isp116x_write_reg32(isp116x, HCCONTROL, val);	/* Disable ports to avoid race in device enumeration */	isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);	isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);	isp116x_show_regs(isp116x);	spin_unlock_irqrestore(&isp116x->lock, flags);	return 0;}/*-----------------------------------------------------------------*/static struct hc_driver isp116x_hc_driver = {	.description = hcd_name,	.product_desc = "ISP116x Host Controller",	.hcd_priv_size = sizeof(struct isp116x),	.irq = isp116x_irq,	.flags = HCD_USB11,	.reset = isp116x_reset,	.start = isp116x_start,	.stop = isp116x_stop,	.urb_enqueue = isp116x_urb_enqueue,	.urb_dequeue = isp116x_urb_dequeue,	.endpoint_disable = isp116x_endpoint_disable,	.get_frame_number = isp116x_get_frame,	.hub_status_data = isp116x_hub_status_data,	.hub_control = isp116x_hub_control,	.bus_suspend = isp116x_bus_suspend,	.bus_resume = isp116x_bus_resume,};/*----------------------------------------------------------------*/static int __init_or_module isp116x_remove(struct platform_device *pdev){	struct usb_hcd *hcd = platform_get_drvdata(pdev);	struct isp116x *isp116x;	struct resource *res;	if (!hcd)		return 0;	isp116x = hcd_to_isp116x(hcd);	remove_debug_file(isp116x);	usb_remove_hcd(hcd);	iounmap(isp116x->data_reg);	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);	release_mem_region(res->start, 2);	iounmap(isp116x->addr_reg);	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);	release_mem_region(res->start, 2);	usb_put_hcd(hcd);	return 0;}#define resource_len(r) (((r)->end - (r)->start) + 1)static int __init isp116x_probe(struct platform_device *pdev){	struct usb_hcd *hcd;	struct isp116x *isp116x;	struct resource *addr, *data;	void __iomem *addr_reg;	void __iomem *data_reg;	int irq;	int ret = 0;	if (pdev->num_resources < 3) {		ret = -ENODEV;		goto err1;	}	data = platform_get_resource(pdev, IORESOURCE_MEM, 0);	addr = platform_get_resource(pdev, IORESOURCE_MEM, 1);	irq = platform_get_irq(pdev, 0);	if (!addr || !data || irq < 0) {		ret = -ENODEV;		goto err1;	}	if (pdev->dev.dma_mask) {		DBG("DMA not supported\n");		ret = -EINVAL;		goto err1;	}	if (!request_mem_region(addr->start, 2, hcd_name)) {		ret = -EBUSY;		goto err1;	}	addr_reg = ioremap(addr->start, resource_len(addr));	if (addr_reg == NULL) {		ret = -ENOMEM;		goto err2;	}	if (!request_mem_region(data->start, 2, hcd_name)) {		ret = -EBUSY;		goto err3;	}	data_reg = ioremap(data->start, resource_len(data));	if (data_reg == NULL) {		ret = -ENOMEM;		goto err4;	}	/* allocate and initialize hcd */	hcd = usb_create_hcd(&isp116x_hc_driver, &pdev->dev, pdev->dev.bus_id);	if (!hcd) {		ret = -ENOMEM;		goto err5;	}	/* this rsrc_start is bogus */	hcd->rsrc_start = addr->start;	isp116x = hcd_to_isp116x(hcd);	isp116x->data_reg = data_reg;	isp116x->addr_reg = addr_reg;	spin_lock_init(&isp116x->lock);	INIT_LIST_HEAD(&isp116x->async);	isp116x->board = pdev->dev.platform_data;	if (!isp116x->board) {		ERR("Platform data structure not initialized\n");		ret = -ENODEV;		goto err6;	}	if (isp116x_check_platform_delay(isp116x)) {		ERR("USE_PLATFORM_DELAY defined, but delay function not "		    "implemented.\n");		ERR("See comments in drivers/usb/host/isp116x-hcd.c\n");		ret = -ENODEV;		goto err6;	}	ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);	if (ret != 0)		goto err6;	create_debug_file(isp116x);	return 0;      err6:	usb_put_hcd(hcd);      err5:	iounmap(data_reg);      err4:	release_mem_region(data->start, 2);      err3:	iounmap(addr_reg);      err2:	release_mem_region(addr->start, 2);      err1:	ERR("init error, %d\n", ret);	return ret;}#ifdef	CONFIG_PM/*  Suspend of platform device*/static int isp116x_suspend(struct platform_device *dev, pm_message_t state){	int ret = 0;	VDBG("%s: state %x\n", __func__, state);	dev->dev.power.power_state = state;	return ret;}/*  Resume platform device*/static int isp116x_resume(struct platform_device *dev){	int ret = 0;	VDBG("%s:  state %x\n", __func__, dev->dev.power.power_state);	dev->dev.power.power_state = PMSG_ON;	return ret;}#else#define	isp116x_suspend    NULL#define	isp116x_resume     NULL#endifstatic struct platform_driver isp116x_driver = {	.probe = isp116x_probe,	.remove = isp116x_remove,	.suspend = isp116x_suspend,	.resume = isp116x_resume,	.driver	= {		.name = (char *)hcd_name,	},};/*-----------------------------------------------------------------*/static int __init isp116x_init(void){	if (usb_disabled())		return -ENODEV;	INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION);	return platform_driver_register(&isp116x_driver);}module_init(isp116x_init);static void __exit isp116x_cleanup(void){	platform_driver_unregister(&isp116x_driver);}module_exit(isp116x_cleanup);

⌨️ 快捷键说明

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