static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
{
	char *regulator_name;

	if (twl->features & TWL6025_SUBCLASS)
		regulator_name = "ldousb";
	else
		regulator_name = "vusb";

	
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);

	
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);

	
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);

	twl->usb3v3 = regulator_get(twl->dev, regulator_name);
	if (IS_ERR(twl->usb3v3))
		return -ENODEV;

	
	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);

	twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);

	return 0;
}
static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
{
	struct twl6030_usb *twl = _twl;
	enum musb_vbus_id_status status = MUSB_UNKNOWN;
	u8 hw_state;
	int ret;

	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);

	if (hw_state & STS_USB_ID) {
		ret = regulator_enable(twl->usb3v3);
		if (ret)
			dev_err(twl->dev, "Failed to enable usb3v3\n");

		twl->asleep = 1;
		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
		status = MUSB_ID_GROUND;
		twl->linkstat = status;
		musb_mailbox(status);
	} else  {
		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
	}
	twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR);

	return IRQ_HANDLED;
}
void id_monitor_work_func(struct work_struct *work)
{
    struct twl6030_usb *twl = container_of(work,
                struct twl6030_usb, vbus_work);
	int status = USB_EVENT_NONE;
	u8 hw_state;
#ifdef CONFIG_USB_MUSB_HDRC_HCD
	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);

	if (hw_state & STS_USB_ID) {

		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
		status = USB_EVENT_ID;
		twl->otg.default_a = true;
		twl->otg.state = OTG_STATE_A_IDLE;
		blocking_notifier_call_chain(&twl->otg.notifier, status,
							twl->otg.gadget);
	} else  {
		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
	}
	twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR);
	twl->linkstat = status;
#endif
    
}
Exemple #4
0
static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
{
	char *regulator_name;

	if (twl->features & TWL6025_SUBCLASS)
		regulator_name = "ldousb";
	else
		regulator_name = "vusb";

	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);

	/* Program CFG_LDO_PD2 register and set VUSB bit */
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);

	/* Program MISC2 register and set bit VUSB_IN_VBAT */
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);

	twl->usb3v3 = regulator_get(twl->dev, regulator_name);
	if (IS_ERR(twl->usb3v3))
		return -ENODEV;

	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);

	/*
	 * Program the USB_ID_CTRL_SET register to enable GND drive
	 * and the ID comparators
	 */
	twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);

	return 0;
}
Exemple #5
0
static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
{
	struct twl6030_usb *twl = _twl;
	int status = USB_EVENT_NONE;
	u8 hw_state;

	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);

	if (hw_state & STS_USB_ID) {

		regulator_enable(twl->usb3v3);
		twl->asleep = 1;
		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1);
		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
								0x10);
		status = USB_EVENT_ID;
		twl->otg.default_a = true;
		twl->otg.state = OTG_STATE_A_IDLE;
		twl->linkstat = status;
		twl->otg.last_event = status;
		atomic_notifier_call_chain(&twl->otg.notifier, status,
							twl->otg.gadget);
	} else  {
		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
								0x10);
		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
								0x1);
	}
	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR, status);

	return IRQ_HANDLED;
}
static int twl6030_start_srp(struct phy_companion *comparator)
{
	struct twl6030_usb *twl = comparator_to_twl(comparator);

	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);

	mdelay(100);
	twl6030_writeb(twl, TWL_MODULE_USB, 0xa0, USB_VBUS_CTRL_CLR);

	return 0;
}
static int twl6030_start_srp(struct usb_otg *otg)
{
	struct twl6030_usb *twl = phy_to_twl(otg->phy);

	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);

	mdelay(100);
	twl6030_writeb(twl, TWL_MODULE_USB, 0xa0, USB_VBUS_CTRL_CLR);

	return 0;
}
Exemple #8
0
static int twl6030_start_srp(struct otg_transceiver *x)
{
	struct twl6030_usb *twl = xceiv_to_twl(x);

	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);

	mdelay(100);
	twl6030_writeb(twl, TWL_MODULE_USB, 0xa0, USB_VBUS_CTRL_CLR);

	return 0;
}
static void otg_set_vbus_work(struct work_struct *data)
{
	struct twl6030_usb *twl = container_of(data, struct twl6030_usb,
								set_vbus_work);


	if (twl->vbus_enable)
		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
							CHARGERUSB_CTRL1);
	else
		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
							CHARGERUSB_CTRL1);
}
Exemple #10
0
static void otg_set_vbus_work(struct work_struct *data)
{
    struct twl6030_usb *twl = container_of(data, struct twl6030_usb,
                                           set_vbus_work);
    /*
     * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
     * register. This enables boost mode.
     */
    if (twl->vbus_enable)
        twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
                       CHARGERUSB_CTRL1);
    else
        twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
                       CHARGERUSB_CTRL1);
}
static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled)
{
	struct twl6030_usb *twl = xceiv_to_twl(x);

	/*
	 * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
	 * register. This enables boost mode.
	 */
	if (enabled)
		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
						CHARGERUSB_CTRL1);
	 else
		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
						CHARGERUSB_CTRL1);
	return 0;
}
static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
{
#ifdef CONFIG_USB_MUSB_HDRC_HCD 
	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP*/
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, USB_BACKUP_REG);
# else
	/* Turn off the ID_WAKEUP_COMP*/
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x0, USB_BACKUP_REG);    
#endif
	/* Set Pull-down is enabled when VUSB and VUSIM is in OFF state */
	//twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x3, CFG_LDO_PD2);

	/* Program MISC2 register and set bit VUSB_IN_VBAT */
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, MISC2);

	/*
	 * Program the VUSB_CFG_VOLTAGE register to set the VUSB
	 * voltage to 3.3V
	 */
	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0x0,
						VUSB_CFG_GRP);
	/* Program the VUSB_CFG_TRANS for ACTIVE state. */
	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0x0,
						VUSB_CFG_TRANS);
	/* Program the VUSB_CFG_TRANS for ACTIVE state. */
	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0x0,
						VUSB_CFG_TRANS);

	/* Program the VUSB_CFG_STATE register to ON on all groups. */
	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0x0,
						VUSB_CFG_STATE);
#if 1
	u8 data2;
	twl_i2c_read_u8(TWL6030_MODULE_ID0, &data2, 0xE6);
	printk("!!!!!BBSPOR_CFG = %2x\n",data2);
	twl_i2c_write_u8(TWL6030_MODULE_ID0, data2 | 0x20, 0xE6);
	printk("!!!!!BBSPOR_CFG = %2x\n",data2 | 0x20);
#endif
	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);
#ifdef CONFIG_USB_MUSB_HDRC_HCD
	/*
	 * Program the USB_ID_CTRL_SET register to enable GND drive
	 * and the ID comparators
	 */
	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_ID_CTRL_SET);
#endif
	return 0;

}
static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
{
	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);

	/* Program CFG_LDO_PD2 register and set VUSB bit */
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);

	/* Program MISC2 register and set bit VUSB_IN_VBAT */
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);

	if (!twl->usb3v3) {
		twl->usb3v3 = regulator_get(twl->dev, "vusb");
		if (IS_ERR(twl->usb3v3))
			return -ENODEV;
	}

	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);

	/*
	 * Program the USB_ID_CTRL_SET register to enable GND drive
	 * and the ID comparators
	 */
	twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);

	/* CHARGERUSB_CTRL3 */
	twl6030_writeb(twl, TWL6030_MODULE_ID1, 0x01, 0xEA);

	return 0;
}
Exemple #14
0
static int twl6030_enable_irq(struct twl6030_usb *twl)
{
	twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);

	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
				REG_INT_MSK_LINE_C);
	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
				REG_INT_MSK_STS_C);

	return 0;
}
static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
{
	char *regulator_name;
	u8 misc2_data = 0;
    u8 rd_reg = 0;

	if (twl->features & TWL6032_SUBCLASS)
		regulator_name = "ldousb";
	else
		regulator_name = "vusb";

	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);

	twl->usb3v3 = regulator_get(twl->dev, regulator_name);
	if (IS_ERR(twl->usb3v3))
		return -ENODEV;

    rd_reg = twl6030_readb(twl, TWL_MODULE_USB, USB_VBUS_CTRL_SET);
    rd_reg = rd_reg | VBUS_ACT_COMP |VBUS_MEAS;
	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
    twl6030_writeb(twl, TWL_MODULE_USB, rd_reg, USB_VBUS_CTRL_SET);

	/*
	 * Program the USB_ID_CTRL_SET register to enable GND drive
	 * and the ID comparators
	 */
    rd_reg = twl6030_readb(twl, TWL_MODULE_USB, USB_ID_CTRL_SET);
    rd_reg = rd_reg | ID_SRC_16U | ID_ACT_COMP |ID_MEAS;
	twl6030_writeb(twl, TWL_MODULE_USB, rd_reg, USB_ID_CTRL_SET);

	/* Program MISC2 register and clear bit VUSB_IN_VBAT */
	misc2_data = twl6030_readb(twl, TWL6030_MODULE_ID0, TWL6030_MISC2);
	misc2_data &= 0xEF;
	twl6030_writeb(twl, TWL6030_MODULE_ID0, misc2_data, TWL6030_MISC2);

	return 0;
}
static int twl6030_usb_resume(struct platform_device *pdev){
    struct twl6030_usb *twl = platform_get_drvdata(pdev);
    //printk("%s \n",__func__);
    int vbus_state = twl6030_readb(twl, TWL6030_MODULE_CHARGER,
						CONTROLLER_STAT1);
    /* AC unplugg can also generate this IRQ
     * we only call the notifier in case of VBUS change
     */
    if (twl->prev_vbus != (vbus_state & VBUS_DET)) {	 
                wake_lock(&twlusb_lock);
		queue_work(vbusid_work_queue, &twl->vbus_work);
    }
    /* Program MISC2 register and set bit VUSB_IN_VBAT */
    twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, MISC2);
    return 0;
}
Exemple #17
0
static int twl6030_enable_irq(struct otg_transceiver *x)
{
	struct twl6030_usb *twl = xceiv_to_twl(x);

	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1);
	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);

	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
				REG_INT_MSK_LINE_C);
	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
				REG_INT_MSK_STS_C);
	twl6030_usb_irq(twl->irq2, twl);
	twl6030_usbotg_irq(twl->irq1, twl);

	return 0;
}
static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
{

	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP*/
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, USB_BACKUP_REG);

	/* Program CFG_LDO_PD2 register and set VUSB bit */
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, CFG_LDO_PD2);

	/* Program MISC2 register and set bit VUSB_IN_VBAT */
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, MISC2);
	/*
	 * Program the VUSB_CFG_VOLTAGE register to set the VUSB
	 * voltage to 3.3V
	 */
	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0x18,
						VUSB_CFG_VOLTAGE);

	/* Program the VUSB_CFG_TRANS for ACTIVE state. */
	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0x3F,
						VUSB_CFG_TRANS);

	/* Program the VUSB_CFG_STATE register to ON on all groups. */
	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0xE1,
						VUSB_CFG_STATE);

	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);

	/*
	 * Program the USB_ID_CTRL_SET register to enable GND drive
	 * and the ID comparators
	 */
	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_ID_CTRL_SET);

	return 0;

}
static void twl6030_usbotg_irq_wq_func(struct work_struct *twl6030_usbotg_irq_wq)
//static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
{
	struct twl6030_usb *twl = tmp_twl_otg; // _twl;
	int status ;

	status = twl6030_readb(twl, TWL_MODULE_USB, USB_ID_INT_SRC);

	if (status & ID_GND) {
		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR,
								status);

		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1);
		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
								0x10);
		status = USB_EVENT_ID;

		blocking_notifier_call_chain(&twl->otg.notifier, status,
							twl->otg.gadget);

		twl->otg.default_a = true;
		twl->otg.state = OTG_STATE_A_IDLE;

	} else if (status & ID_FLOAT) {

		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR,
								status);
		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
								0x10);
		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
								0x1);

		twl->otg.default_a = false;
		twl->otg.state = OTG_STATE_B_IDLE;
		blocking_notifier_call_chain(&twl->otg.notifier, status,
					twl->otg.gadget);
	}
	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR, status);

	sysfs_notify(&twl->dev->kobj, NULL, "vbus");

	return IRQ_HANDLED;
}
Exemple #20
0
static int twl6030_set_hz_mode(struct otg_transceiver *x, bool enabled)
{
    u8 val;
    struct twl6030_usb *twl;

    if (!x)
        return -ENODEV;

    twl = xceiv_to_twl(x);

    /* set/reset USB charger in High impedence mode on VBUS */
    val = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
                        CHARGERUSB_CTRL1);

    if (enabled)
        val |= HZ_MODE;
    else
        val &= ~HZ_MODE;

    twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , val,
                   CHARGERUSB_CTRL1);

    return 0;
}
Exemple #21
0
static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
{

#ifndef CONFIG_USB_MUSB_PERIPHERAL
	struct twl6030_usb *twl = _twl;
	int status = USB_EVENT_NONE;
	u8 hw_state, misc2_data;

	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);

	if (hw_state & STS_USB_ID) {

		if (twl->otg.state == OTG_STATE_A_IDLE)
			return IRQ_HANDLED;

		/* Program MISC2 register and set bit VUSB_IN_VBAT */
		misc2_data = twl6030_readb(twl, TWL6030_MODULE_ID0,
						TWL6030_MISC2);
		misc2_data |= 0x10;
		twl6030_writeb(twl, TWL6030_MODULE_ID0, misc2_data,
						TWL6030_MISC2);
		regulator_enable(twl->usb3v3);
		twl->asleep = 1;
		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
		status = USB_EVENT_ID;
		twl->otg.default_a = true;
		twl->otg.state = OTG_STATE_A_IDLE;
		twl->linkstat = status;
		twl->otg.last_event = status;
		atomic_notifier_call_chain(&twl->otg.notifier, status,
							twl->otg.gadget);
	} else  {
		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
	}
	twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR);
#endif

	return IRQ_HANDLED;
}
static int __devinit twl6030_usb_probe(struct platform_device *pdev)
{
	struct twl6030_usb	*twl;
	int			status;
	struct twl4030_usb_data *pdata;
	struct device *dev = &pdev->dev;
	pdata = dev->platform_data;

	twl = kzalloc(sizeof *twl, GFP_KERNEL);
	if (!twl)
		return -ENOMEM;

	twl->dev		= &pdev->dev;
	twl->irq1		= platform_get_irq(pdev, 0);
	twl->irq2		= platform_get_irq(pdev, 1);
	twl->otg.dev		= twl->dev;
	twl->otg.label		= "twl6030";
	twl->otg.set_host	= twl6030_set_host;
	twl->otg.set_peripheral	= twl6030_set_peripheral;
	twl->otg.set_vbus	= twl6030_set_vbus;
	twl->otg.set_hz_mode	= twl6030_set_hz_mode;
	twl->otg.init		= twl6030_phy_init;
	twl->otg.shutdown	= twl6030_phy_shutdown;
	twl->otg.enable_irq	= twl6030_enable_irq;


	/*We need to make sure ID comparator is ON*/
	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);

	/* init spinlock for workqueue */
	spin_lock_init(&twl->lock);

	wake_lock_init(&twl_lock, WAKE_LOCK_SUSPEND, "twl_wake_lock");

	otg_set_transceiver(&twl->otg);

	platform_set_drvdata(pdev, twl);
	if (device_create_file(&pdev->dev, &dev_attr_vbus))
		dev_warn(&pdev->dev, "could not create sysfs file\n");

	BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier);

	twl->irq_enabled = true;
	status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
			"twl6030_usb", twl);
	if (status < 0) {
		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
			twl->irq1, status);
		device_remove_file(twl->dev, &dev_attr_vbus);
		kfree(twl);
		return status;
	}

	status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
			"twl6030_usb", twl);
	if (status < 0) {
		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
			twl->irq2, status);
		free_irq(twl->irq1, twl);
		device_remove_file(twl->dev, &dev_attr_vbus);
		kfree(twl);
		return status;
	}

	twl->asleep = 0;
	pdata->phy_init(dev);
	twl6030_enable_irq(&twl->otg);
	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");

	return 0;
}
Exemple #23
0
static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
{

#ifndef CONFIG_USB_MUSB_PERIPHERAL
    struct twl6030_usb *twl = _twl;
    int status = USB_EVENT_NONE;
    u8 hw_state, misc2_data;

    hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);

    if (hw_state & STS_USB_ID) {
        if (twl->otg.state != OTG_STATE_A_IDLE) {
            /* Program MISC2 register and set bit VUSB_IN_VBAT */
            misc2_data = twl6030_readb(twl, TWL6030_MODULE_ID0,
                                       TWL6030_MISC2);

            misc2_data |= 0x10;
            twl6030_writeb(twl, TWL6030_MODULE_ID0, misc2_data,
                           TWL6030_MISC2);

            regulator_enable(twl->usb3v3);
            twl->asleep = 1;
            twl6030_writeb(twl, TWL_MODULE_USB, 0x1,
                           USB_ID_INT_EN_HI_CLR);
            twl6030_writeb(twl, TWL_MODULE_USB, 0x10,
                           USB_ID_INT_EN_HI_SET);

            status = USB_EVENT_ID;
            twl->otg.default_a = true;
            twl->otg.state = OTG_STATE_A_IDLE;
            twl->linkstat = status;
            twl->otg.last_event = status;
            atomic_notifier_call_chain(&twl->otg.notifier, status,
                                       twl->otg.gadget);
            /*
             * NOTE:
             * This is workaround for the TWL6032 thats missed VBUS
             * detection interrupts while OPA_MODE is set to 1 in
             * the CHARGERUSB_CTRL1.
             * Just set prev_vbus to VBUS_DET and do sysfs_notify.
             */
            if (twl->features & TWL6032_SUBCLASS) {
                sysfs_notify(&twl->dev->kobj, NULL, "vbus");
                twl->prev_vbus = VBUS_DET;
            }
        }
    } else  {
        /*
         * NOTE:
         * This is workaround for the TWL6032 thats missed VBUS
         * detection interrupts while OPA_MODE is set to 1 in
         * the CHARGERUSB_CTRL1. Just set BOOST mode for OTG to off
         * and VBUS interrupts will start to work.
         */
        if (twl->features & TWL6032_SUBCLASS) {
            twl->vbus_enable = 0;
            twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
                           CHARGERUSB_CTRL1);
        }

        twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
        twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
    }
    /* clear interrupt flags*/
    twl6030_writeb(twl, TWL_MODULE_USB, 0x1F, USB_ID_INT_LATCH_CLR);
#endif

    return IRQ_HANDLED;
}
Exemple #24
0
    /* clear interrupt flags*/
    twl6030_writeb(twl, TWL_MODULE_USB, 0x1F, USB_ID_INT_LATCH_CLR);
#endif
}

static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
{
#ifndef CONFIG_USB_MUSB_PERIPHERAL
    struct twl6030_usb *twl = (struct twl6030_usb*)_twl;

    if(!twl)
        return IRQ_HANDLED;

    schedule_work(&twl->usbotg_irq_work);
#endif
    return IRQ_HANDLED;
}

#else /*                 */
static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
{
    struct twl6030_usb *twl = _twl;
    int status;
    u8 vbus_state, hw_state, misc2_data;
    unsigned charger_type;

    hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);

    vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
                               CONTROLLER_STAT1);
    vbus_state = vbus_state & VBUS_DET;

    /* Ignore charger events other than VBUS */
    if (vbus_state == twl->prev_vbus)
        return IRQ_HANDLED;

    if ((vbus_state) && !(hw_state & STS_USB_ID)) {
        /* Program MISC2 register and set bit VUSB_IN_VBAT */
        misc2_data = twl6030_readb(twl, TWL6030_MODULE_ID0,
                                   TWL6030_MISC2);
        misc2_data |= 0x10;
        twl6030_writeb(twl, TWL6030_MODULE_ID0, misc2_data,
                       TWL6030_MISC2);

        regulator_enable(twl->usb3v3);
        twl6030_phy_suspend(&twl->otg, 0);
        charger_type = omap4_charger_detect();
        twl6030_phy_suspend(&twl->otg, 1);
        if ((charger_type == POWER_SUPPLY_TYPE_USB_CDP)
                || (charger_type == POWER_SUPPLY_TYPE_USB)) {

            status = USB_EVENT_VBUS;
            twl->otg.default_a = false;
            twl->asleep = 1;
            twl->otg.state = OTG_STATE_B_IDLE;
            twl->linkstat = status;
            twl->otg.last_event = status;
        } else if (charger_type == POWER_SUPPLY_TYPE_USB_DCP) {
            regulator_disable(twl->usb3v3);
            status = USB_EVENT_CHARGER;
            twl->usb_cinlimit_mA = 1800;
            twl->otg.state = OTG_STATE_B_IDLE;
            twl->linkstat = status;
            twl->otg.last_event = status;
        } else {
            regulator_disable(twl->usb3v3);
            goto vbus_notify;
        }
        atomic_notifier_call_chain(&twl->otg.notifier,
                                   status, &charger_type);
    }
    if (!vbus_state) {
        status = USB_EVENT_NONE;
        twl->linkstat = status;
        twl->otg.last_event = status;
        atomic_notifier_call_chain(&twl->otg.notifier,
                                   status, twl->otg.gadget);
        if (twl->asleep) {
            regulator_disable(twl->usb3v3);
            twl->asleep = 0;
            /* Program MISC2 register and clear bit VUSB_IN_VBAT */
            misc2_data = twl6030_readb(twl, TWL6030_MODULE_ID0,
                                       TWL6030_MISC2);
            misc2_data &= 0xEF;
            twl6030_writeb(twl, TWL6030_MODULE_ID0, misc2_data,
                           TWL6030_MISC2);
        }
    }

vbus_notify:
    sysfs_notify(&twl->dev->kobj, NULL, "vbus");
    twl->prev_vbus = vbus_state;
    return IRQ_HANDLED;
}