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

📄 twl4030_usb.c

📁 omap3 linux 2.6 用nocc去除了冗余代码
💻 C
📖 第 1 页 / 共 2 页
字号:
					SPKRLEFT_BIASEN);	twl4030_usb_clear_bits(twl, MCPC_CTRL,					HS_UART |					RTSCTSSW |					OUT64K |					VOICESW |					EXTSWC |					EXTSWR);	twl4030_usb_set_bits(twl, MCPC_IO_CTRL, TXDTYP);	twl4030_usb_clear_bits(twl, MCPC_IO_CTRL,					RTSTYP |					CTSTYP |					RXD_PU |					CTS_NPU |					MICBIASEN);	twl4030_usb_set_bits(twl, POWER_CTRL, OTG_ENAB);	/* setup transceiver mode for FS */	twl4030_usb_clear_bits(twl, OTG_CTRL, DPPULLDOWN | DMPULLDOWN);	twl4030_usb_clear_bits(twl, FUNC_CTRL, XCVRSELECT_MASK | OPMODE_MASK);	twl4030_usb_set_bits(twl, FUNC_CTRL, OPMODE_NORMAL | XCVRSELECT_FS);	twl4030_usb_clear_bits(twl, IFC_CTRL, CARKITMODE);	twl4030_usb_set_bits(twl, IFC_CTRL, FSLSSERIALMODE_3PIN);	twl4030_usb_clear_bits(twl, OTHER_IFC_CTRL,					CEA2011_MODE | FSLSSERIALMODE_4PIN);	twl4030_usb_clear_bits(twl, OTHER_IFC_CTRL2, ULPI_4PIN_2430);	twl4030_usb_set_bits(twl, OTHER_IFC_CTRL2, ULPI_TXEN_POL);}static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode){	twl->usb_mode = mode;	switch (mode) {	case T2_USB_MODE_ULPI:		twl4030_usb_clear_bits(twl, IFC_CTRL, CARKITMODE);		twl4030_usb_set_bits(twl, POWER_CTRL, OTG_ENAB);		twl4030_usb_clear_bits(twl, FUNC_CTRL,					XCVRSELECT_MASK | OPMODE_MASK);		break;	case T2_USB_MODE_CEA2011_3PIN:		twl4030_cea2011_3_pin_FS_setup(twl);		break;	default:		/* power on defaults */		break;	};}static void hs_usb_init(struct twl4030_usb *twl){	twl->usb_mode = T2_USB_MODE_ULPI;	return;}static void twl4030_i2c_access(int on){	unsigned long timeout;	int val;	if ((val = twl4030_usb_read(PHY_CLK_CTRL)) >= 0) {		if (on) {			/* enable DPLL to access PHY registers over I2C */			val |= REQ_PHY_DPLL_CLK;			twl4030_usb_write_verify(PHY_CLK_CTRL, (u8)val);			timeout = jiffies + HZ;			while (!(twl4030_usb_read(PHY_CLK_CTRL_STS) &							PHY_DPLL_CLK)				&& time_before(jiffies, timeout)) {				udelay(10);			}			if (!(twl4030_usb_read(PHY_CLK_CTRL_STS) &							PHY_DPLL_CLK))				printk(KERN_ERR "Timeout setting T2 HSUSB "						"PHY DPLL clock\n");		} else {			/* let ULPI control the DPLL clock */			val &= ~REQ_PHY_DPLL_CLK;			twl4030_usb_write_verify(PHY_CLK_CTRL, (u8)val);		}	}i2c_failed:	return;}static void usb_irq_enable(int rising, int falling){	u8 val;	/* edge setup */	twl4030_i2c_read_u8_verify(TWL4030_MODULE_INT, &val, REG_PWR_EDR1);	val &= ~(USB_PRES_RISING | USB_PRES_FALLING);	if (rising)		val = val | USB_PRES_RISING;	if (falling)		val = val | USB_PRES_FALLING;	twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val, REG_PWR_EDR1);	/* un-mask interrupt */	twl4030_i2c_read_u8_verify(TWL4030_MODULE_INT, &val, REG_PWR_IMR1);	val &= ~USB_PRES;	twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val, REG_PWR_IMR1);i2c_failed:	return;}static void usb_irq_disable(void){	u8 val;	/* undo edge setup */	twl4030_i2c_read_u8_verify(TWL4030_MODULE_INT, &val, REG_PWR_EDR1);	val &= ~(USB_PRES_RISING | USB_PRES_FALLING);	twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val, REG_PWR_EDR1);	/* mask interrupt */	twl4030_i2c_read_u8_verify(TWL4030_MODULE_INT, &val, REG_PWR_IMR1);	val |= USB_PRES;	twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val, REG_PWR_IMR1);i2c_failed:	return;}void twl4030_phy_suspend(int controller_off);void twl4030_phy_resume(void);extern int twl4030charger_usb_en(int enable);static irqreturn_t twl4030_usb_irq(int irq, void *_twl){	int ret = IRQ_NONE;	u8 val;	u8 sih_ctrl;	/* save previous value of SIH_CTRL and disable clear_on_read */	twl4030_i2c_read_u8(TWL4030_MODULE_INT, &sih_ctrl, REG_PWR_SIH_CTRL);	twl4030_i2c_write_u8(TWL4030_MODULE_INT, (sih_ctrl & ~COR),			     REG_PWR_SIH_CTRL);	twl4030_i2c_read_u8_verify(TWL4030_MODULE_INT, &val, REG_PWR_ISR1);	/* this interrupt line may be shared */	if(!(val & USB_PRES))		goto done;	/* clear the interrupt */	twl4030_i2c_write_u8(TWL4030_MODULE_INT, USB_PRES, REG_PWR_ISR1);	/* action based on cable attach or detach */	twl4030_i2c_read_u8_verify(TWL4030_MODULE_INT, &val, REG_PWR_EDR1);	if (val & USB_PRES_RISING) {		twl4030_phy_resume();	} else {		twl4030_phy_suspend(0);	}	twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER,				&val,				0x0F /*STS_HW_CONDITIONS*/);	if( (val & (1<<2)) || (val & (1<<7)) ){ /* STS_USB or STS_VBUS */		printk(KERN_DEBUG "USB connected\n");	}	else {		printk(KERN_DEBUG "USB disconnected\n");	}	ret = IRQ_HANDLED;i2c_failed:done:	/* restore previous value of SIH_CTRL */	twl4030_i2c_write_u8(TWL4030_MODULE_INT, sih_ctrl, REG_PWR_SIH_CTRL);	return ret;}static void twl4030_phy_power(struct twl4030_usb *twl, int on){	u8 pwr;	pwr = twl4030_usb_read(PHY_PWR_CTRL);	if (on) {		pwr &= ~PHYPWD;		twl4030_usb_write_verify(PHY_PWR_CTRL, pwr);		twl4030_usb_write(PHY_CLK_CTRL,				  twl4030_usb_read(PHY_CLK_CTRL) |					(CLOCKGATING_EN | CLK32K_EN));	} else  {		pwr |= PHYPWD;		twl4030_usb_write_verify(PHY_PWR_CTRL, pwr);	}i2c_failed:	return;}static void twl4030_usb_ldo_init(struct twl4030_usb *twl){	/* Enable writing to power configuration registers */	twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY);	twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY);	/* put VUSB3V1 LDO in active state */	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, 0, VUSB_DEDICATED2);	/* input to VUSB3V1 LDO is from VBAT, not VBUS */	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, 0x14, VUSB_DEDICATED1);	/* turn on 3.1V regulator */	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, 0x20, VUSB3V1_DEV_GRP);	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, 0, VUSB3V1_TYPE);	/* turn on 1.5V regulator */	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, 0x20, VUSB1V5_DEV_GRP);	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, 0, VUSB1V5_TYPE);	/* turn on 1.8V regulator */	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, 0x20, VUSB1V8_DEV_GRP);	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, 0, VUSB1V8_TYPE);	/* disable access to power configuration registers */	twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECIEVER, 0, PROTECT_KEY);}#define METHOD	3	/* Method 1 does not work */void twl4030_phy_suspend(int controller_off){	struct twl4030_usb *twl = the_transceiver;	if (controller_off)		usb_irq_disable();	if (twl->asleep)		return;	if (!controller_off)		/* enable rising edge interrupt to detect cable attach */		usb_irq_enable(1, 0);	twl4030_phy_power(twl, 0);	twl->asleep = 1;	/* Release USB constraint on OFF/RET */	if (twl->usb_power_constraint){		constraint_remove(twl->usb_power_constraint);	}	return;}EXPORT_SYMBOL(twl4030_phy_suspend);void twl4030_phy_resume(void){	struct twl4030_usb *twl = the_transceiver;	if (!twl->asleep)		return;	/* Acquire USB constraint on OFF/RET */	if (twl->usb_power_constraint)		constraint_set(twl->usb_power_constraint,					CO_LATENCY_MPUOFF_COREON);	/* enable falling edge interrupt to detect cable detach */	usb_irq_enable(0, 1);	twl4030_phy_power(twl, 1);	twl4030_i2c_access(1);	twl4030_usb_set_mode(twl, twl->usb_mode);	if (twl->usb_mode == T2_USB_MODE_ULPI)		twl4030_i2c_access(0);	twl->asleep = 0;	return;}EXPORT_SYMBOL(twl4030_phy_resume);static int __init twl4030_usb_init(void){	struct twl4030_usb	*twl;	int status;	u8 val;	if (the_transceiver)		return 0;	twl = kcalloc(1, sizeof *twl, GFP_KERNEL);	if (!twl)		return 0;	the_transceiver = twl;	twl->irq = TWL4030_MODIRQ_PWR;	usb_irq_disable();	status = request_irq(twl->irq, twl4030_usb_irq,		IRQF_DISABLED | IRQF_SHARED, "twl4030_usb", twl);	if (status < 0) {		printk(KERN_DEBUG "can't get IRQ %d, err %d\n",			twl->irq, status);		kfree(twl);		return -ENODEV;	}	hs_usb_init(twl);	twl4030_usb_ldo_init(twl);	twl4030_phy_power(twl, 1);	twl4030_i2c_access(1);	twl4030_usb_set_mode(twl, twl->usb_mode);	if (twl->usb_mode == T2_USB_MODE_ULPI)		twl4030_i2c_access(0);	twl->asleep = 0;	twl->usb_power_constraint = NULL;	/* Get handle to USB Constraint for OFF/RETENTION */	twl->usb_power_constraint = constraint_get("usb", &cnstr_id);	printk(KERN_INFO "Initialized TWL4030 USB module");	return 0;}static void __exit twl4030_usb_exit(void){	struct twl4030_usb *twl = the_transceiver;	int val;	usb_irq_disable();	free_irq(twl->irq, twl);	/* set transceiver mode to power on defaults */	twl4030_usb_set_mode(twl, -1);	/* autogate 60MHz ULPI clock,	 * clear dpll clock request for i2c access,	 * disable 32KHz	 */	if ((val = twl4030_usb_read(PHY_CLK_CTRL)) >= 0) {		val |= CLOCKGATING_EN;		val &= ~(CLK32K_EN | REQ_PHY_DPLL_CLK);		twl4030_usb_write(PHY_CLK_CTRL, (u8)val);	}	/* disable complete OTG block */	twl4030_usb_clear_bits(twl, POWER_CTRL, OTG_ENAB);	twl4030_phy_power(twl, 0);	if (twl->usb_power_constraint)		constraint_put(twl->usb_power_constraint);	kfree(twl);}subsys_initcall(twl4030_usb_init);module_exit(twl4030_usb_exit);MODULE_AUTHOR("Texas Instruments, Inc.");MODULE_DESCRIPTION("TWL4030 USB transceiver driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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