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

📄 ucb1x00-core.cbb

📁 基于pxa270的touch screen的源码
💻 CBB
📖 第 1 页 / 共 2 页
字号:
		ucb1x00_disable(ucb);		spin_unlock_irqrestore(&ucb->lock, flags);	}}/** *	ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt *	@ucb: UCB1x00 structure describing chip *	@idx: interrupt index *	@devid: device id. * *	Disable the interrupt source and remove the handler.  devid must *	match the devid passed when hooking the interrupt. * *	Returns zero on success, or one of the following errors: *	 -EINVAL if the interrupt index is invalid *	 -ENOENT if devid does not match */int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid){	struct ucb1x00_irq *irq;	int ret;	if (idx >= 16)		goto bad;	irq = ucb->irq_handler + idx;	ret = -ENOENT;	spin_lock_irq(&ucb->lock);	if (irq->devid == devid) {		ucb->irq_ris_enbl &= ~(1 << idx);		ucb->irq_fal_enbl &= ~(1 << idx);		ucb1x00_enable(ucb);		ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);		ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);		ucb1x00_disable(ucb);		irq->fn = NULL;		irq->devid = NULL;		ret = 0;	}	spin_unlock_irq(&ucb->lock);	return ret;bad:	printk(KERN_ERR "%s: freeing bad irq %d\n", __FUNCTION__, idx);	return -EINVAL;}/* * Try to probe our interrupt, rather than relying on lots of * hard-coded machine dependencies.  For reference, the expected * IRQ mappings are: * *  	Machine		Default IRQ *	adsbitsy	IRQ_GPCIN4 *	cerf		IRQ_GPIO_UCB1200_IRQ *	flexanet	IRQ_GPIO_GUI *	freebird	IRQ_GPIO_FREEBIRD_UCB1300_IRQ *	graphicsclient	ADS_EXT_IRQ(8) *	graphicsmaster	ADS_EXT_IRQ(8) *	lart		LART_IRQ_UCB1200 *	omnimeter	IRQ_GPIO23 *	pfs168		IRQ_GPIO_UCB1300_IRQ *	simpad		IRQ_GPIO_UCB1300_IRQ *	shannon		SHANNON_IRQ_GPIO_IRQ_CODEC *	yopy		IRQ_GPIO_UCB1200_IRQ */static int __init ucb1x00_detect_irq(struct ucb1x00 *ucb){	unsigned long mask;        	mask = probe_irq_on();	if (!mask)		return NO_IRQ;     printk("ucb1x00_detect_irq \n");	/*	 * Enable the ADC interrupt.	 */	ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);	ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC);	ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);	ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);	/*	 * Cause an ADC interrupt.	 */	ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);	ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);	/*	 * Wait for the conversion to complete.	 */	while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0);	ucb1x00_reg_write(ucb, UCB_ADC_CR, 0);	/*	 * Disable and clear interrupt.	 */	ucb1x00_reg_write(ucb, UCB_IE_RIS, 0);	ucb1x00_reg_write(ucb, UCB_IE_FAL, 0);	ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);	ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);	/*	 * Read triggered interrupt.	 */	return probe_irq_off(mask);}/* * This configures the UCB1x00 layer depending on the machine type * we're running on.  The UCB1x00 drivers should not contain any * machine dependencies. * * We can get rid of some of these dependencies by using existing * facilities provided by the kernel - namely IRQ probing.  The * machine specific files are expected to setup the IRQ levels on * initialisation.  With any luck, we'll get rid of all the * machine dependencies here. */static int __init ucb1x00_configure(struct ucb1x00 *ucb){	unsigned int irq_gpio_pin = 0;	int irq, default_irq = NO_IRQ;   //     ucb->irq = UCB1400_IRQ;#ifdef CONFIG_ARCH_SA1100	if (machine_is_adsbitsy())		default_irq = IRQ_GPCIN4;//	if (machine_is_assabet())//		default_irq = IRQ_GPIO23;#ifdef CONFIG_SA1100_CERF	if (machine_is_cerf())		default_irq = IRQ_GPIO_UCB1200_IRQ;#endif#ifdef CONFIG_SA1100_FREEBIRD	if (machine_is_freebird())		default_irq = IRQ_GPIO_FREEBIRD_UCB1300_IRQ;#endif#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || defined(CONFIG_SA1100_GRAPICSMASTER)	if (machine_is_graphicsclient() || machine_is_graphicsmaster())		default_irq = ADS_EXT_IRQ(8);#endif#ifdef CONFIG_SA1100_LART	if (machine_is_lart()) {		default_irq = LART_IRQ_UCB1200;		irq_gpio_pin = LART_GPIO_UCB1200;	}#endif	if (machine_is_omnimeter())		default_irq = IRQ_GPIO23;#ifdef CONFIG_SA1100_PFS168	if (machine_is_pfs168())		default_irq = IRQ_GPIO_UCB1300_IRQ;#endif#ifdef CONFIG_SA1100_SIMPAD	if (machine_is_simpad())		default_irq = IRQ_GPIO_UCB1300_IRQ;#endif#ifdef CONFIG_SA1100_SIMPUTER	if (machine_is_simputer()) {		default_irq = IRQ_GPIO_UCB1300_IRQ;		irq_gpio_pin = GPIO_UCB1300_IRQ;    }#endif	if (machine_is_shannon())		default_irq = SHANNON_IRQ_GPIO_IRQ_CODEC;#ifdef CONFIG_SA1100_YOPY	if (machine_is_yopy())		default_irq = IRQ_GPIO_UCB1200_IRQ;#endif#ifdef CONFIG_SA1100_ACCELENT	if (machine_is_accelent_sa()) {		ucb->irq = IRQ_GPIO_UCB1200_IRQ;		irq_gpio_pin = GPIO_UCB1200_IRQ;	}#endif#endif /* CONFIG_ARCH_SA1100 */#ifdef CONFIG_ARCH_PXA_IDP	if (machine_is_pxa_idp()) {		default_irq = TOUCH_PANEL_IRQ;		irq_gpio_pin = IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ);		GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin);	}#endif#ifdef CONFIG_ARCH_TRIZEPS2	if (machine_is_trizeps2()) {		default_irq = TOUCH_PANEL_IRQ;		irq_gpio_pin = IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ);		GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin);	}#endif#ifdef CONFIG_ARCH_MAINSTONE	if (machine_is_mainstone()) {		ucb->irq = MAINSTONE_AC97_IRQ;	}#endif#ifdef CONFIG_ARCH_XSBASE270	if (machine_is_xsbase270()) {	set_GPIO_IRQ_edge(13,GPIO_RISING_EDGE);	enable_irq(IRQ_GPIO(13));      	//ucb->irq = UCB1400_IRQ;	}#endif#ifdef CONFIG_PXA_CERF_PDA	if (machine_is_pxa_cerf()) {		irq_gpio_pin = CERF_GPIO_UCB1400_IRQ;	}#endif	/*	 * Eventually, this will disappear.	 */	if (irq_gpio_pin)#ifdef CONFIG_ARCH_PXA_IDP		set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_FALLING_EDGE);#else		set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE);#endif	irq = ucb1x00_detect_irq(ucb);	if (irq != NO_IRQ) {		if (default_irq != NO_IRQ && irq != default_irq)			printk(KERN_ERR "UCB1x00: probed IRQ%d != default IRQ%d\n",				irq, default_irq);		if (irq == default_irq)			printk(KERN_ERR "UCB1x00: probed IRQ%d correctly. "				"Please remove machine dependencies from "				"ucb1x00-core.c\n", irq);		ucb->irq = irq;	} else {		printk(KERN_ERR "UCB1x00: IRQ probe failed, using IRQ%d\n",			default_irq);		ucb->irq = default_irq;	}	return ucb->irq == NO_IRQ ? -ENODEV : 0;}struct ucb1x00 *my_ucb;static int ucb1x00_init_helper(void){	struct mcp *mcp;	unsigned int id;	int ret = -ENODEV;	mcp = mcp_get();	if (!mcp)		goto no_mcp;	mcp_enable(mcp);	id = mcp_reg_read(mcp, UCB_ID);	if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_1400) {		printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);		goto out;	}	/* distinguish between UCB1400 revs 1B and 2A */	if (id == UCB_ID_1400 && mcp_reg_read(mcp, 0x00) == 0x002a)		id = UCB_ID_1400_BUGGY;	my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);	ret = -ENOMEM;	if (!my_ucb)		goto out;#ifdef CONFIG_ARCH_SA1100	if (machine_is_shannon()) {		/* reset the codec */		GPDR |= SHANNON_GPIO_CODEC_RESET;		GPCR = SHANNON_GPIO_CODEC_RESET;		GPSR = SHANNON_GPIO_CODEC_RESET;	}#endif	memset(my_ucb, 0, sizeof(struct ucb1x00));	spin_lock_init(&my_ucb->lock);	spin_lock_init(&my_ucb->io_lock);	sema_init(&my_ucb->adc_sem, 1);	my_ucb->id  = id;	my_ucb->mcp = mcp;	ret = ucb1x00_configure(my_ucb);	if (ret)		goto out;	init_waitqueue_head(&my_ucb->irq_wait);	ret = request_irq(my_ucb->irq, ucb1x00_irq, 0, "UCB1x00", my_ucb);	if (ret) {		printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",			my_ucb->irq, ret);		goto irq_err;	}#ifdef CONFIG_PM	my_ucb->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ucb1x00_pm);	if (my_ucb->pmdev == NULL)		printk("ucb1x00: unable to register in PM.\n");	else		my_ucb->pmdev->data = my_ucb;#endif	init_completion(&my_ucb->complete);	ret = kernel_thread(ucb1x00_thread, my_ucb, CLONE_FS | CLONE_FILES);	if (ret >= 0) {		wait_for_completion(&my_ucb->complete);		ret = 0;		goto out;	}	free_irq(my_ucb->irq, my_ucb);irq_err:	kfree(my_ucb);	my_ucb = NULL;out:	mcp_disable(mcp);no_mcp:	return ret;}/** *	ucb1x00_get - get the UCB1x00 structure describing a chip *	@ucb: UCB1x00 structure describing chip * *	Return the UCB1x00 structure describing a chip. * *	FIXME: Currently very noddy indeed, which currently doesn't *	matter since we only support one chip. */struct ucb1x00 *ucb1x00_get(void){	if( !my_ucb) ucb1x00_init_helper();	return my_ucb;}static int __init ucb1x00_init(void){	/* check if driver is already initialized */	if( my_ucb) return 0;	return ucb1x00_init_helper();}static void __exit ucb1x00_exit(void){	send_sig(SIGKILL, my_ucb->rtask, 1);	wait_for_completion(&my_ucb->complete);	free_irq(my_ucb->irq, my_ucb);	kfree(my_ucb);	my_ucb = 0;}module_init(ucb1x00_init);module_exit(ucb1x00_exit);EXPORT_SYMBOL(ucb1x00_get);EXPORT_SYMBOL(ucb1x00_io_set_dir);EXPORT_SYMBOL(ucb1x00_io_write);EXPORT_SYMBOL(ucb1x00_io_read);EXPORT_SYMBOL(ucb1x00_adc_enable);EXPORT_SYMBOL(ucb1x00_adc_read);EXPORT_SYMBOL(ucb1x00_adc_disable);EXPORT_SYMBOL(ucb1x00_hook_irq);EXPORT_SYMBOL(ucb1x00_free_irq);EXPORT_SYMBOL(ucb1x00_enable_irq);EXPORT_SYMBOL(ucb1x00_disable_irq);MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");MODULE_DESCRIPTION("UCB1x00 core driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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